diff --git a/.gitignore b/.gitignore
index d92c19c88b771f93c86183ed55afa7be9be09ba8..a03c5e3933569d05747d2a3e1219fbce7da36a60 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
 *~
 \#*\#
 .\#*
+node_modules
diff --git a/browserid/lib/wsapi.js b/browserid/lib/wsapi.js
index 981d12c0f2027f1af5fa59b2afae28ec0eeb1e9f..e7d757956aa8ddae61e51ab6f7ccc4230ce0d0be 100644
--- a/browserid/lib/wsapi.js
+++ b/browserid/lib/wsapi.js
@@ -54,7 +54,7 @@ function setup(app) {
     // get inputs from get data!
     var email = url.parse(req.url, true).query['email'];
     db.emailKnown(email, function(known) {
-      httputils.jsonResponse(resp, known);
+      resp.json(known);
     });
   });
 
@@ -88,9 +88,7 @@ function setup(app) {
         // served over an encrypted (SSL) session.  guten, yah.
       };
 
-      httputils.jsonResponse(resp, true);
-
-      // let's now kick out a verification email!
+      resp.json(true);
       email.sendVerificationEmail(stageParams.email, stageParams.site, secret);
 
     } catch(e) {
@@ -122,9 +120,9 @@ function setup(app) {
                                    function(registered) {
                                      if (registered) {
                                        delete req.session.pendingAddition;
-                                       httputils.jsonResponse(resp, "complete");
+                                       resp.json('complete');
                                      } else {
-                                       httputils.jsonResponse(resp, "pending");
+                                       resp.json('pending');
                                      }
                                    });
     } else {
@@ -136,9 +134,9 @@ function setup(app) {
         if (hash === v.hash) {
           delete req.session.pendingVerification;
           req.session.authenticatedUser = v.email;
-          httputils.jsonResponse(resp, "complete");
+          resp.json('complete');
         } else {
-          httputils.jsonResponse(resp, "pending");
+          resp.json('pending');
         }
       });
     }
@@ -156,7 +154,8 @@ function setup(app) {
         if (!req.session) req.session = {};
         req.session.authenticatedUser = req.body.email;
       }
-      httputils.jsonResponse(resp, success);
+
+      resp.json(success);
     });
   });
 
@@ -169,7 +168,7 @@ function setup(app) {
       // store the email being added in session data
       req.session.pendingAddition = req.body.email;
 
-      httputils.jsonResponse(resp, true);
+      resp.json(true);
 
       // let's now kick out a verification email!
       email.sendVerificationEmail(req.body.email, req.body.site, secret);
@@ -187,7 +186,7 @@ function setup(app) {
         console.log("error removing email " + email);
         httputils.badRequest(resp, error.toString());
       } else {
-        httputils.jsonResponse(resp, true);
+        resp.json(true);
       }});
   });
 
@@ -197,13 +196,13 @@ function setup(app) {
         console.log("error cancelling account : " + error.toString());
         httputils.badRequest(resp, error.toString());
       } else {
-        httputils.jsonResponse(resp, true);
+        resp.json(true);
       }});
   });
 
   app.post('/wsapi/set_key', checkAuthed, checkParams(["email", "pubkey"]), function (req, resp) {
     db.addKeyToEmail(req.session.authenticatedUser, req.body.email, req.body.pubkey, function (rv) {
-      httputils.jsonResponse(resp, rv);
+      resp.json(rv);
     });
   });
 
@@ -211,18 +210,18 @@ function setup(app) {
     // if they're authenticated for an email address that we don't know about,
     // then we should purge the stored cookie
     if (!isAuthed(req)) {
-      httputils.jsonResponse(resp, false);
+      resp.json(false);
     } else {
       db.emailKnown(req.session.authenticatedUser, function (known) {
         if (!known) req.session = {}
-        httputils.jsonResponse(resp, known);
+        resp.json(known);
       });
     }
   });
 
   app.post('/wsapi/logout', function(req,resp) {
     req.session = {};
-    httputils.jsonResponse(resp, "ok");
+    resp.json('ok');
   });
 
   app.post('/wsapi/sync_emails', checkAuthed, function(req,resp) {
@@ -230,7 +229,7 @@ function setup(app) {
 
     db.getSyncResponse(req.session.authenticatedUser, emails, function(err, syncResponse) {
       if (err) httputils.serverError(resp, err);
-      else httputils.jsonResponse(resp, syncResponse);
+      else resp.json(syncResponse);
     });
   });
 
@@ -238,9 +237,9 @@ function setup(app) {
     db.gotVerificationSecret(req.query.token, function(e) {
       if (e) {
         console.log("error completing the verification: " + e);
-        httputils.jsonResponse(resp, false);
+        resp.json(false);
       } else {
-        httputils.jsonResponse(resp, true);
+        resp.json(true);
       }
     });
   });
diff --git a/package.json b/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..e7be06a03b958d2eefbd4f971249619571981e8c
--- /dev/null
+++ b/package.json
@@ -0,0 +1,16 @@
+{
+    "name": "browserid"
+  , "version": "0.0.1"
+  , "private": true
+  , "dependencies": {
+      "express": "2.4.3"
+    , "xml2js": "0.1.5"
+    , "sqlite": "1.0.3"
+    , "nodemailer": "0.1.18"
+    , "mustache": "0.3.1-dev"
+    , "cookie-sessions": "0.0.2"
+    , "vows": "0.5.8"
+    , "bcrypt": "0.2.3"
+    , "ejs": "0.4.3"
+  }
+}
\ No newline at end of file
diff --git a/primary/lib/wsapi.js b/primary/lib/wsapi.js
index 16ac8c90c6f0a132ec96eab66e6d28ee077f5476..7de31c829bcea6144e8cb2a6e67543c6651d72de 100644
--- a/primary/lib/wsapi.js
+++ b/primary/lib/wsapi.js
@@ -47,7 +47,7 @@ exports.username_available = function(req, resp) {
   var username = normalizeUsername(url.parse(req.url, true).query['username']);
   logRequest("username_available", {username: username});
   db.usernameKnown(username, function(known) { 
-    httputils.jsonResponse(resp, known);
+    resp.json(known);
   });
 };
 
@@ -66,12 +66,12 @@ exports.create_user = function(req, resp) {
     db.create_user(normalized_username, getArgs["pass"], function(error) {
       if (error) {
         logRequest("create_user", error);
-        httputils.jsonResponse(resp, undefined);
+        resp.json(undefined);
       } else {
         if (!req.session) req.session = {};
         db.usernameToUserID(normalized_username, function(userid) {
           req.session.userid = userid;
-          httputils.jsonResponse(resp, {username: normalized_username, id: userid});
+          resp.json({ username: normalized_username, id: userid });
         });
       }
     });
@@ -95,7 +95,7 @@ exports.authenticate_user = function(req, resp) {
       req.session.userid = userid;
     }
     var rp = {username: normalized_username, status: userid != null};
-    httputils.jsonResponse(resp, rp);
+    resp.json(rp);
   });
 };
 
@@ -104,7 +104,7 @@ exports.signout = function(req, resp) {
   if (req.session) {
     req.session.userid = undefined;// can I reference undefined safely like this?
   }
-  httputils.jsonResponse(resp, {});
+  resp.json({});
 };
 
 exports.add_key = function (req, resp) {
@@ -123,13 +123,13 @@ exports.add_key = function (req, resp) {
   logRequest("add_key", getArgs);
   db.addKeyToAccount(req.session.userid, getArgs.pubkey, function (rv) {
     logRequest("add_key", "Success");
-    httputils.jsonResponse(resp, rv);
+    resp.json(rv);
   });
 };
 
 exports.am_authed = function(req,resp) {
   logRequest("am_authed", req.session);
-  httputils.jsonResponse(resp, isAuthed(req));
+  resp.json(isAuthed(req));
 };
 
 exports.current_username = function(req,resp) {
@@ -140,16 +140,16 @@ exports.current_username = function(req,resp) {
       db.userIDToUsername(req.session.userid, function(username) {
         if (username !== undefined) {
           logRequest("current_username", username);
-          httputils.jsonResponse(resp, username);
+          resp.json(username);
         } else {
           logRequest("current_username", "userid doesn't exist: " + req.session.userid);
           req.session.userid = undefined;
-          httputils.jsonResponse(resp, false);
+          resp.json(false);
         }
       });
     } else {
       logRequest("current_username", "notAuthed");
-      httputils.jsonResponse(resp, false);
+      resp.json(false);
     }
   } catch (e) {
     console.log(e);
diff --git a/verifier/app.js b/verifier/app.js
index 4fbd67b20f4cdcd56d8e9050e1ada6482eca6a50..2503a31be9d9a96453519c08f6a5a04623e69773 100644
--- a/verifier/app.js
+++ b/verifier/app.js
@@ -15,7 +15,7 @@ function doVerify(req, resp, next) {
   var audience = (req.query && req.query.audience) ? req.query.audience : req.body.audience;
 
   if (!(assertion && audience))
-    return httputils.jsonResponse(resp, {status:"failure", reason:"need assertion and audience"});
+    return resp.json({ status: "failure", reason: "need assertion and audience" });
 
   // allow client side XHR to access this WSAPI, see
   // https://developer.mozilla.org/en/http_access_control
@@ -42,15 +42,15 @@ function doVerify(req, resp, next) {
             "valid-until" : payload["valid-until"],
             issuer : payload.issuer
           };
-          httputils.jsonResponse(resp, result);
+          resp.json(result);
         },
         function(errorObj) {
-          httputils.jsonResponse(resp, {status:"failure", reason:errorObj});
+          resp.json({ status: "failure", reason: errorObj });
         }
       );
   } catch (e) {
     console.log(e.stack);
-    httputils.jsonResponse(resp, {status:"failure", reason:e.toString()});
+    resp.json({ status: "failure", reason: e.toString() });
   }
 }