From cd510be50148bdd426997b5fd8b1d55b445d7a33 Mon Sep 17 00:00:00 2001
From: Camil Staps
Date: Sun, 10 May 2015 22:40:54 +0200
Subject: Bugfix gulpfile

---
 gulpfile.js | 1 +
 1 file changed, 1 insertion(+)

diff --git a/gulpfile.js b/gulpfile.js
index a3c28e1..23b113c 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -92,6 +92,7 @@ gulp.task('styles', function() {
                 return file;
             }
         }}))
+        .pipe(changed(dst, { destination: 'style.css' }))
         .pipe(gulpif(isBootswatchFile, foreach(function(stream, file) {
             var themeName = path.basename(path.dirname(file.path)),
                 content = replaceAll(baseContent, bootswatch_theme, themeName),
-- 
cgit v1.2.3


From 2664d857350392f4900851cdaf6cbcf71aca334a Mon Sep 17 00:00:00 2001
From: Camil Staps
Date: Sun, 10 May 2015 22:41:00 +0200
Subject: Login form start

---
 src/css/forms.less           |  4 ++--
 src/include/layout-main.jade | 12 ++++++++++++
 src/index.jade               | 11 +++++++++--
 src/js/forms.js              |  5 +++++
 4 files changed, 28 insertions(+), 4 deletions(-)

diff --git a/src/css/forms.less b/src/css/forms.less
index 233bde5..6ddc244 100644
--- a/src/css/forms.less
+++ b/src/css/forms.less
@@ -1,3 +1,3 @@
-label {
-    display: block;
+#login-block {
+    display: none;
 }
\ No newline at end of file
diff --git a/src/include/layout-main.jade b/src/include/layout-main.jade
index 72331ee..df3fdc5 100644
--- a/src/include/layout-main.jade
+++ b/src/include/layout-main.jade
@@ -18,10 +18,22 @@ html(lang="en")
               li.active(role='presentation'): a(href=val,title=key)= key
             else
               li(role='presentation'): a(href=val,title=key)= key
+          li(role='presentation'): a.btn-botleagues-login(href='#',title='Login') Login
         h3 Botleagues
 
       #messages
 
+      #login-block
+        form.form-inline#login-form
+          .form-group
+            label.control-label(for='login-email') Email:
+            input.form-control#login-email(type='email')
+          .form-group
+            label.control-label(for='login-password') Password:
+            input.form-control#login-password(type='password')
+          a.btn.btn-default#login-submit(href='#') Login
+
+
       block content
 
       footer.footer: :markdown
diff --git a/src/index.jade b/src/index.jade
index f405884..6b6a175 100644
--- a/src/index.jade
+++ b/src/index.jade
@@ -11,14 +11,21 @@ block content
       a.btn.btn-lg.btn-success.pull-right(href='/register', role='button') Register now
 
   .row
-    .col-lg-6
+    .col-lg-4
       h4 Subheading
       p Donec id elit non mi porta gravida at eget metus. Maecenas faucibus mollis interdum.
       h4 Subheading
       p Morbi leo risus, porta ac consectetur ac, vestibulum at eros. Cras mattis consectetur purus sit amet fermentum.
       h4 Subheading
       p Maecenas sed diam eget risus varius blandit sit amet non magna.
-    .col-lg-6
+    .col-lg-4
+      h4 Subheading
+      p Donec id elit non mi porta gravida at eget metus. Maecenas faucibus mollis interdum.
+      h4 Subheading
+      p Morbi leo risus, porta ac consectetur ac, vestibulum at eros. Cras mattis consectetur purus sit amet fermentum.
+      h4 Subheading
+      p Maecenas sed diam eget risus varius blandit sit amet non magna.
+    .col-lg-4
       h4 Subheading
       p Donec id elit non mi porta gravida at eget metus. Maecenas faucibus mollis interdum.
       h4 Subheading
diff --git a/src/js/forms.js b/src/js/forms.js
index 24f0f43..e096794 100644
--- a/src/js/forms.js
+++ b/src/js/forms.js
@@ -9,4 +9,9 @@ $('form.form-register').submit(function(){
     }, BotleaguesCallback.register);
 
     event.preventDefault();
+});
+
+$('.btn-botleagues-login').focus(function(){
+    $('#login-block').slideDown();
+    $('#login-email').focus();
 });
\ No newline at end of file
-- 
cgit v1.2.3


From f51ce6f4acf28c224ec4a02f35ae35726cdc4c38 Mon Sep 17 00:00:00 2001
From: Camil Staps
Date: Tue, 12 May 2015 22:31:07 +0200
Subject: Working login, but doesn't save token yet

---
 gulpfile.js                  |  2 +-
 src/css/forms.less           |  6 ++++++
 src/include/layout-main.jade | 10 ++++------
 src/js/Botleagues.js         | 24 ++++++++++++++++++++----
 src/js/BotleaguesCallback.js | 13 +++++++++++++
 src/js/BotleaguesFrontend.js |  8 +-------
 src/js/forms.js              |  7 ++++++-
 7 files changed, 51 insertions(+), 19 deletions(-)

diff --git a/gulpfile.js b/gulpfile.js
index 23b113c..181462c 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -92,7 +92,7 @@ gulp.task('styles', function() {
                 return file;
             }
         }}))
-        .pipe(changed(dst, { destination: 'style.css' }))
+        //.pipe(changed(dst, { destination: 'style.css' }))
         .pipe(gulpif(isBootswatchFile, foreach(function(stream, file) {
             var themeName = path.basename(path.dirname(file.path)),
                 content = replaceAll(baseContent, bootswatch_theme, themeName),
diff --git a/src/css/forms.less b/src/css/forms.less
index 6ddc244..e29f4d7 100644
--- a/src/css/forms.less
+++ b/src/css/forms.less
@@ -1,3 +1,9 @@
 #login-block {
     display: none;
+
+    #login-form {
+        display: inline-block;
+        float: right;
+        margin-bottom: 0.5em;
+    }
 }
\ No newline at end of file
diff --git a/src/include/layout-main.jade b/src/include/layout-main.jade
index df3fdc5..7b15138 100644
--- a/src/include/layout-main.jade
+++ b/src/include/layout-main.jade
@@ -24,15 +24,13 @@ html(lang="en")
       #messages
 
       #login-block
-        form.form-inline#login-form
+        form.form-inline#login-form(action='#',method='post')
           .form-group
-            label.control-label(for='login-email') Email:
-            input.form-control#login-email(type='email')
+            input.form-control#login-email(type='email',placeholder='Email')
           .form-group
-            label.control-label(for='login-password') Password:
-            input.form-control#login-password(type='password')
+            input.form-control#login-password(type='password',placeholder='Password')
           a.btn.btn-default#login-submit(href='#') Login
-
+        br(style='clear:both;')
 
       block content
 
diff --git a/src/js/Botleagues.js b/src/js/Botleagues.js
index f9d34b7..2ab1bc7 100644
--- a/src/js/Botleagues.js
+++ b/src/js/Botleagues.js
@@ -2,7 +2,9 @@ function Botleagues(){}
 
 Botleagues.url = 'https://api.local.botleagues.camilstaps.nl';
 
-Botleagues.request = function(user_options, callback) {
+Botleagues.request = function(user_options) {
+    var callback = user_options.callback;
+
     var options = {
         endpoint: null,
         method: 'GET',
@@ -11,16 +13,30 @@ Botleagues.request = function(user_options, callback) {
             callback(data.responseJSON);
         }
     };
+
+    var url = Botleagues.url + '/' + user_options['endpoint'];
+    delete user_options['callback'];
+    delete user_options['endpoint'];
+
     for (var name in user_options) {
         options[name] = user_options[name];
     }
 
-    var url = Botleagues.url + '/' + options['endpoint'];
-    delete options['endpoint'];
-
     jQuery.ajax(url, options);
 };
 
 Botleagues.redirect = function(user_options) {
     window.location = Botleagues.url + '/' + user_options['endpoint'];
+};
+
+Botleagues.login = function(username, password) {
+    Botleagues.request({
+        endpoint: 'user_token',
+        method: 'POST',
+        callback: BotleaguesCallback.login,
+        async: false,
+        headers: {
+            'Authorization': 'Basic ' + btoa(username + ':' + password)
+        }
+    });
 };
\ No newline at end of file
diff --git a/src/js/BotleaguesCallback.js b/src/js/BotleaguesCallback.js
index f162e7c..3b1de02 100644
--- a/src/js/BotleaguesCallback.js
+++ b/src/js/BotleaguesCallback.js
@@ -29,4 +29,17 @@ BotleaguesCallback.register = function(data) {
             }
         }
     }
+};
+
+BotleaguesCallback.login = function(data) {
+    if (data.user_token) {
+        BotleaguesFrontend.error({
+            message: "Login successful!",
+            type: 'success'
+        });
+    } else {
+        BotleaguesFrontend.error({
+            message: data.error ? data.error : "Could not login."
+        });
+    }
 };
\ No newline at end of file
diff --git a/src/js/BotleaguesFrontend.js b/src/js/BotleaguesFrontend.js
index e9ab570..c25a7f2 100644
--- a/src/js/BotleaguesFrontend.js
+++ b/src/js/BotleaguesFrontend.js
@@ -18,11 +18,5 @@ BotleaguesFrontend.error = function(user_options) {
 
     html = $(html);
 
-    html.prependTo(options.prepend_to).delay(3000).fadeOut().queue(html.remove);
-};
-
-BotleaguesFrontend.login = function() {
-    Botleagues.redirect({
-        endpoint: 'user/login?redirect=http://local.botleagues.camilstaps.nl/'
-    });
+    html.hide().prependTo(options.prepend_to).slideDown().delay(3000).fadeOut().queue(html.remove);
 };
\ No newline at end of file
diff --git a/src/js/forms.js b/src/js/forms.js
index e096794..c6bdffe 100644
--- a/src/js/forms.js
+++ b/src/js/forms.js
@@ -14,4 +14,9 @@ $('form.form-register').submit(function(){
 $('.btn-botleagues-login').focus(function(){
     $('#login-block').slideDown();
     $('#login-email').focus();
-});
\ No newline at end of file
+});
+var login = function(){
+    Botleagues.login($('#login-email').val(), $('#login-password').val());
+};
+$('#login-submit').click(login);
+$('#login-form').submit(login);
\ No newline at end of file
-- 
cgit v1.2.3


From 49a41885b1f5167056ba97c5e573f8a833b8055d Mon Sep 17 00:00:00 2001
From: Camil Staps
Date: Wed, 13 May 2015 07:48:45 +0200
Subject: Nicer login form

---
 src/include/layout-main.jade | 3 ++-
 src/js/forms.js              | 6 ++----
 2 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/src/include/layout-main.jade b/src/include/layout-main.jade
index 7b15138..fac12f2 100644
--- a/src/include/layout-main.jade
+++ b/src/include/layout-main.jade
@@ -29,7 +29,8 @@ html(lang="en")
             input.form-control#login-email(type='email',placeholder='Email')
           .form-group
             input.form-control#login-password(type='password',placeholder='Password')
-          a.btn.btn-default#login-submit(href='#') Login
+          .form-group
+            button.btn.btn-default.pull-right#login-submit(role='submit') Login
         br(style='clear:both;')
 
       block content
diff --git a/src/js/forms.js b/src/js/forms.js
index c6bdffe..dfecb7f 100644
--- a/src/js/forms.js
+++ b/src/js/forms.js
@@ -15,8 +15,6 @@ $('.btn-botleagues-login').focus(function(){
     $('#login-block').slideDown();
     $('#login-email').focus();
 });
-var login = function(){
+$('#login-form').submit(function(){
     Botleagues.login($('#login-email').val(), $('#login-password').val());
-};
-$('#login-submit').click(login);
-$('#login-form').submit(login);
\ No newline at end of file
+});
\ No newline at end of file
-- 
cgit v1.2.3


From 3841987127e33a17a0c070b42c9293e282fa8a72 Mon Sep 17 00:00:00 2001
From: Camil Staps
Date: Wed, 13 May 2015 08:09:25 +0200
Subject: Save token information in cookies

---
 src/js/Botleagues.js         | 1 -
 src/js/BotleaguesCallback.js | 3 +++
 src/js/BotleaguesFrontend.js | 4 ++++
 src/js/forms.js              | 1 +
 4 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/src/js/Botleagues.js b/src/js/Botleagues.js
index 2ab1bc7..c219a3d 100644
--- a/src/js/Botleagues.js
+++ b/src/js/Botleagues.js
@@ -34,7 +34,6 @@ Botleagues.login = function(username, password) {
         endpoint: 'user_token',
         method: 'POST',
         callback: BotleaguesCallback.login,
-        async: false,
         headers: {
             'Authorization': 'Basic ' + btoa(username + ':' + password)
         }
diff --git a/src/js/BotleaguesCallback.js b/src/js/BotleaguesCallback.js
index 3b1de02..ce91d50 100644
--- a/src/js/BotleaguesCallback.js
+++ b/src/js/BotleaguesCallback.js
@@ -37,6 +37,9 @@ BotleaguesCallback.login = function(data) {
             message: "Login successful!",
             type: 'success'
         });
+        $.cookie(BotleaguesFrontend.cookie_login_user_id, data.user_token.userId);
+        $.cookie(BotleaguesFrontend.cookie_login_token, data.user_token.token);
+        $.cookie(BotleaguesFrontend.cookie_login_valid_till, Date.parse(data.user_token.valid_till));
     } else {
         BotleaguesFrontend.error({
             message: data.error ? data.error : "Could not login."
diff --git a/src/js/BotleaguesFrontend.js b/src/js/BotleaguesFrontend.js
index c25a7f2..be80f31 100644
--- a/src/js/BotleaguesFrontend.js
+++ b/src/js/BotleaguesFrontend.js
@@ -1,5 +1,9 @@
 function BotleaguesFrontend(){}
 
+BotleaguesFrontend.cookie_login_user_id = 'botleagues_login_user_id';
+BotleaguesFrontend.cookie_login_token = 'botleagues_login_token';
+BotleaguesFrontend.cookie_login_valid_till = 'botleagues_login_valid_till';
+
 BotleaguesFrontend.error = function(user_options) {
     options = {
         dismissable: true,
diff --git a/src/js/forms.js b/src/js/forms.js
index dfecb7f..6a567a8 100644
--- a/src/js/forms.js
+++ b/src/js/forms.js
@@ -17,4 +17,5 @@ $('.btn-botleagues-login').focus(function(){
 });
 $('#login-form').submit(function(){
     Botleagues.login($('#login-email').val(), $('#login-password').val());
+    return false;
 });
\ No newline at end of file
-- 
cgit v1.2.3


From 3252fb165b74a9daf2ce27ac05b6c5a1c22018d4 Mon Sep 17 00:00:00 2001
From: Camil Staps
Date: Wed, 13 May 2015 08:15:31 +0200
Subject: Save user's email in cookie

---
 src/js/Botleagues.js         | 6 ++++--
 src/js/BotleaguesCallback.js | 1 +
 src/js/BotleaguesFrontend.js | 2 ++
 3 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/src/js/Botleagues.js b/src/js/Botleagues.js
index c219a3d..f11c995 100644
--- a/src/js/Botleagues.js
+++ b/src/js/Botleagues.js
@@ -29,13 +29,15 @@ Botleagues.redirect = function(user_options) {
     window.location = Botleagues.url + '/' + user_options['endpoint'];
 };
 
-Botleagues.login = function(username, password) {
+Botleagues.login = function(email, password) {
     Botleagues.request({
         endpoint: 'user_token',
         method: 'POST',
         callback: BotleaguesCallback.login,
         headers: {
-            'Authorization': 'Basic ' + btoa(username + ':' + password)
+            'Authorization': 'Basic ' + btoa(email + ':' + password)
         }
     });
+
+    $.cookie(BotleaguesFrontend.cookie_login_email, email);
 };
\ No newline at end of file
diff --git a/src/js/BotleaguesCallback.js b/src/js/BotleaguesCallback.js
index ce91d50..3e7e512 100644
--- a/src/js/BotleaguesCallback.js
+++ b/src/js/BotleaguesCallback.js
@@ -44,5 +44,6 @@ BotleaguesCallback.login = function(data) {
         BotleaguesFrontend.error({
             message: data.error ? data.error : "Could not login."
         });
+        $.removeCookie(BotleaguesFrontend.cookie_login_email);
     }
 };
\ No newline at end of file
diff --git a/src/js/BotleaguesFrontend.js b/src/js/BotleaguesFrontend.js
index be80f31..b365743 100644
--- a/src/js/BotleaguesFrontend.js
+++ b/src/js/BotleaguesFrontend.js
@@ -1,5 +1,7 @@
 function BotleaguesFrontend(){}
 
+$.cookie.json = true;
+BotleaguesFrontend.cookie_login_email = 'botleagues_login_email';
 BotleaguesFrontend.cookie_login_user_id = 'botleagues_login_user_id';
 BotleaguesFrontend.cookie_login_token = 'botleagues_login_token';
 BotleaguesFrontend.cookie_login_valid_till = 'botleagues_login_valid_till';
-- 
cgit v1.2.3


From e7f88122ace11130d566e57461f14e383917f5a8 Mon Sep 17 00:00:00 2001
From: Camil Staps
Date: Wed, 13 May 2015 09:45:54 +0200
Subject: Show login email if logged in

---
 src/include/foot.jade        |  4 +++-
 src/include/layout-main.jade |  4 ++--
 src/js/BotleaguesCallback.js |  3 ++-
 src/js/main.js               | 16 ++++++++++++++++
 4 files changed, 23 insertions(+), 4 deletions(-)
 create mode 100644 src/js/main.js

diff --git a/src/include/foot.jade b/src/include/foot.jade
index 1e383f2..4c8a7a1 100644
--- a/src/include/foot.jade
+++ b/src/include/foot.jade
@@ -2,4 +2,6 @@ script(src='/assets/js/script.js', type='text/javascript')
 script(src='/assets/js/Botleagues.js', type='text/javascript')
 script(src='/assets/js/BotleaguesCallback.js', type='text/javascript')
 script(src='/assets/js/BotleaguesFrontend.js', type='text/javascript')
-script(src='/assets/js/forms.js', type='text/javascript')
\ No newline at end of file
+
+script(src='/assets/js/forms.js', type='text/javascript')
+script(src='/assets/js/main.js', type='text/javascript')
\ No newline at end of file
diff --git a/src/include/layout-main.jade b/src/include/layout-main.jade
index fac12f2..164a7b2 100644
--- a/src/include/layout-main.jade
+++ b/src/include/layout-main.jade
@@ -12,13 +12,13 @@ html(lang="en")
       -var menu = { 'Home': '/', 'About': '/about', 'Contact': '/contact' };
 
       .header.clearfix
-        nav: ul.nav.nav-pills.pull-right
+        nav: ul.nav.nav-pills.pull-right#nav
           each val, key in menu
             if selected === val
               li.active(role='presentation'): a(href=val,title=key)= key
             else
               li(role='presentation'): a(href=val,title=key)= key
-          li(role='presentation'): a.btn-botleagues-login(href='#',title='Login') Login
+          li.login-link(role='presentation'): a.btn-botleagues-login(href='#',title='Login') Login
         h3 Botleagues
 
       #messages
diff --git a/src/js/BotleaguesCallback.js b/src/js/BotleaguesCallback.js
index 3e7e512..ea837fd 100644
--- a/src/js/BotleaguesCallback.js
+++ b/src/js/BotleaguesCallback.js
@@ -39,7 +39,8 @@ BotleaguesCallback.login = function(data) {
         });
         $.cookie(BotleaguesFrontend.cookie_login_user_id, data.user_token.userId);
         $.cookie(BotleaguesFrontend.cookie_login_token, data.user_token.token);
-        $.cookie(BotleaguesFrontend.cookie_login_valid_till, Date.parse(data.user_token.valid_till));
+        $.cookie(BotleaguesFrontend.cookie_login_valid_till,
+            (new Date()).getTime() + Date.parse(data.user_token.valid_till) - Date.parse(data.user_token.updated_at));
     } else {
         BotleaguesFrontend.error({
             message: data.error ? data.error : "Could not login."
diff --git a/src/js/main.js b/src/js/main.js
new file mode 100644
index 0000000..04b5c6f
--- /dev/null
+++ b/src/js/main.js
@@ -0,0 +1,16 @@
+$(document).ready(function(){
+
+    // Show profile link instead of login if user is logged in
+    var email = $.cookie(BotleaguesFrontend.cookie_login_email);
+    console.log(email);
+    if (typeof email != 'undefined' && $.cookie(BotleaguesFrontend.cookie_login_valid_till) > (new Date()).getTime()) {
+        $('#nav .login-link').remove();
+        $('<li>').append(
+            $('<a>')
+                .attr('role', 'presentation')
+                .attr('title', 'User profile')
+                .attr('href', '/profile')
+                .text(email))
+            .appendTo($('#nav'));
+    }
+});
\ No newline at end of file
-- 
cgit v1.2.3


From 40b70fdd0a66de2ff660c99555c2ee5292c82bd8 Mon Sep 17 00:00:00 2001
From: Camil Staps
Date: Wed, 13 May 2015 10:38:07 +0200
Subject: Reload page on successful login

---
 src/js/BotleaguesCallback.js | 3 +++
 src/js/BotleaguesFrontend.js | 4 ++++
 src/js/main.js               | 1 -
 3 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/src/js/BotleaguesCallback.js b/src/js/BotleaguesCallback.js
index ea837fd..b4916c1 100644
--- a/src/js/BotleaguesCallback.js
+++ b/src/js/BotleaguesCallback.js
@@ -37,10 +37,13 @@ BotleaguesCallback.login = function(data) {
             message: "Login successful!",
             type: 'success'
         });
+        
         $.cookie(BotleaguesFrontend.cookie_login_user_id, data.user_token.userId);
         $.cookie(BotleaguesFrontend.cookie_login_token, data.user_token.token);
         $.cookie(BotleaguesFrontend.cookie_login_valid_till,
             (new Date()).getTime() + Date.parse(data.user_token.valid_till) - Date.parse(data.user_token.updated_at));
+
+        BotleaguesFrontend.refresh();
     } else {
         BotleaguesFrontend.error({
             message: data.error ? data.error : "Could not login."
diff --git a/src/js/BotleaguesFrontend.js b/src/js/BotleaguesFrontend.js
index b365743..752cd7a 100644
--- a/src/js/BotleaguesFrontend.js
+++ b/src/js/BotleaguesFrontend.js
@@ -25,4 +25,8 @@ BotleaguesFrontend.error = function(user_options) {
     html = $(html);
 
     html.hide().prependTo(options.prepend_to).slideDown().delay(3000).fadeOut().queue(html.remove);
+};
+
+BotleaguesFrontend.refresh = function() {
+    location.reload();
 };
\ No newline at end of file
diff --git a/src/js/main.js b/src/js/main.js
index 04b5c6f..d3ab688 100644
--- a/src/js/main.js
+++ b/src/js/main.js
@@ -2,7 +2,6 @@ $(document).ready(function(){
 
     // Show profile link instead of login if user is logged in
     var email = $.cookie(BotleaguesFrontend.cookie_login_email);
-    console.log(email);
     if (typeof email != 'undefined' && $.cookie(BotleaguesFrontend.cookie_login_valid_till) > (new Date()).getTime()) {
         $('#nav .login-link').remove();
         $('<li>').append(
-- 
cgit v1.2.3


From f88789856be8a484bb1800a1b1695c2ac4b8a3b1 Mon Sep 17 00:00:00 2001
From: Camil Staps
Date: Wed, 13 May 2015 12:32:27 +0200
Subject: Logout

---
 src/include/layout-main.jade |  4 +++-
 src/js/Botleagues.js         |  5 +++++
 src/js/BotleaguesFrontend.js | 11 +++++++++++
 src/js/main.js               | 29 ++++++++++++++++++++---------
 src/logout.jade              | 11 +++++++++++
 5 files changed, 50 insertions(+), 10 deletions(-)
 create mode 100644 src/logout.jade

diff --git a/src/include/layout-main.jade b/src/include/layout-main.jade
index 164a7b2..4b521a9 100644
--- a/src/include/layout-main.jade
+++ b/src/include/layout-main.jade
@@ -38,4 +38,6 @@ html(lang="en")
       footer.footer: :markdown
         &copy; [ViviSoft](http://vivisoft.nl/) 2015
 
-    include ./foot.jade
\ No newline at end of file
+    include ./foot.jade
+
+    block js
\ No newline at end of file
diff --git a/src/js/Botleagues.js b/src/js/Botleagues.js
index f11c995..21dd5d7 100644
--- a/src/js/Botleagues.js
+++ b/src/js/Botleagues.js
@@ -40,4 +40,9 @@ Botleagues.login = function(email, password) {
     });
 
     $.cookie(BotleaguesFrontend.cookie_login_email, email);
+};
+
+Botleagues.logout = function(){
+    BotleaguesFrontend.clearLoginCookies();
+    BotleaguesFrontend.redirect('/');
 };
\ No newline at end of file
diff --git a/src/js/BotleaguesFrontend.js b/src/js/BotleaguesFrontend.js
index 752cd7a..b94708e 100644
--- a/src/js/BotleaguesFrontend.js
+++ b/src/js/BotleaguesFrontend.js
@@ -29,4 +29,15 @@ BotleaguesFrontend.error = function(user_options) {
 
 BotleaguesFrontend.refresh = function() {
     location.reload();
+};
+
+BotleaguesFrontend.redirect = function(location) {
+    window.location = location;
+}
+
+BotleaguesFrontend.clearLoginCookies = function() {
+    $.removeCookie(BotleaguesFrontend.cookie_login_email);
+    $.removeCookie(BotleaguesFrontend.cookie_login_user_id);
+    $.removeCookie(BotleaguesFrontend.cookie_login_token);
+    $.removeCookie(BotleaguesFrontend.cookie_login_valid_till);
 };
\ No newline at end of file
diff --git a/src/js/main.js b/src/js/main.js
index d3ab688..4444273 100644
--- a/src/js/main.js
+++ b/src/js/main.js
@@ -3,13 +3,24 @@ $(document).ready(function(){
     // Show profile link instead of login if user is logged in
     var email = $.cookie(BotleaguesFrontend.cookie_login_email);
     if (typeof email != 'undefined' && $.cookie(BotleaguesFrontend.cookie_login_valid_till) > (new Date()).getTime()) {
-        $('#nav .login-link').remove();
-        $('<li>').append(
-            $('<a>')
-                .attr('role', 'presentation')
-                .attr('title', 'User profile')
-                .attr('href', '/profile')
-                .text(email))
-            .appendTo($('#nav'));
+        setupLoginMenu(email);
     }
-});
\ No newline at end of file
+});
+
+function setupLoginMenu(email) {
+    $('#nav .login-link').remove();
+    $('<li>').append(
+        $('<a>')
+            .attr('role', 'presentation')
+            .attr('title', 'User profile')
+            .attr('href', '/profile')
+            .text(email))
+        .appendTo($('#nav'));
+    $('<li>').append(
+        $('<a>')
+            .attr('role', 'presentation')
+            .attr('title', 'Logout')
+            .attr('href', '/logout')
+            .text('Logout'))
+        .appendTo($('#nav'));
+}
\ No newline at end of file
diff --git a/src/logout.jade b/src/logout.jade
new file mode 100644
index 0000000..f94e608
--- /dev/null
+++ b/src/logout.jade
@@ -0,0 +1,11 @@
+extends ./include/layout-main.jade
+
+block menu
+  -var selected = '/logout'
+
+block content
+  p Login you out...
+
+block js
+  script(type='text/javascript')
+    |$(document).ready(function(){ Botleagues.logout(); });
\ No newline at end of file
-- 
cgit v1.2.3


From ac9a9e119e66a55db2100d2bdcfa0914a1c78d96 Mon Sep 17 00:00:00 2001
From: Camil Staps
Date: Wed, 13 May 2015 17:06:51 +0200
Subject: Separate build task for own styles & 3rd-party styles

---
 gulpfile.js | 26 +++++++++++++++++++++-----
 1 file changed, 21 insertions(+), 5 deletions(-)

diff --git a/gulpfile.js b/gulpfile.js
index 181462c..1aa41fc 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -30,7 +30,7 @@ gulp.task('default', [], function() {
 });
 
 gulp.task('all', [], function() {
-    gulp.start('fonts', 'styles', 'scripts', 'images', 'jade');
+    gulp.start('fonts', 'styles', 'scripts', 'images', 'jade', '3rd-party-styles');
 });
 
 gulp.task('rebuild', ['clean'], function() {
@@ -55,7 +55,7 @@ gulp.task('fonts', function() {
         .pipe(gulp.dest(dst));
 });
 
-gulp.task('styles', function() {
+gulp.task('3rd-party-styles', function() {
     
     var baseContent = 
         '@import "./bower_components/bootstrap/less/bootstrap.less";' + 
@@ -77,8 +77,7 @@ gulp.task('styles', function() {
     
     var fileList = [
         './bower_components/bootswatch/' + bootswatch_theme + '/bootswatch.less', 
-        './bower_components/fontawesome/css/font-awesome.css',
-        './src/css/style.less'
+        './bower_components/fontawesome/css/font-awesome.css'
     ];
 
     var dst = './build/assets/css';
@@ -92,7 +91,6 @@ gulp.task('styles', function() {
                 return file;
             }
         }}))
-        //.pipe(changed(dst, { destination: 'style.css' }))
         .pipe(gulpif(isBootswatchFile, foreach(function(stream, file) {
             var themeName = path.basename(path.dirname(file.path)),
                 content = replaceAll(baseContent, bootswatch_theme, themeName),
@@ -117,6 +115,24 @@ gulp.task('styles', function() {
         .pipe(gulp.dest(dst));
 });
 
+gulp.task('styles', function() {
+    
+    var sources = [
+        './src/css/style.less',
+        './src/css/forms.less'
+    ];
+
+    var dst = './build/assets/css';
+    var dst_filename = 'style.css';
+    
+    return gulp.src(sources)
+        .pipe(changed(dst, {destination: dst_filename}))
+        .pipe(less())
+        .pipe(concat(dst_filename))
+        .pipe(minifycss())
+        .pipe(gulp.dest(dst));
+});
+
 gulp.task('scripts', function(){
     var fileList = [
         './bower_components/jquery/dist/jquery.min.js',
-- 
cgit v1.2.3


From c69bb86ab6eeace2e448b26983c6e78ccef656af Mon Sep 17 00:00:00 2001
From: Camil Staps
Date: Wed, 13 May 2015 17:40:21 +0200
Subject: Gulpfile: bootswatch-theme specific styles; superhero -> lumen

---
 gulpfile.js | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/gulpfile.js b/gulpfile.js
index 1aa41fc..9bd83f8 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -21,7 +21,7 @@ var gulp = require('gulp'),
     merge = require('merge-stream'),
     del = require('del');
 
-var bootswatch_theme = 'superhero';
+var bootswatch_theme = 'lumen';
 
 var production = false;
 
@@ -118,8 +118,9 @@ gulp.task('3rd-party-styles', function() {
 gulp.task('styles', function() {
     
     var sources = [
-        './src/css/style.less',
-        './src/css/forms.less'
+        './src/css/forms.less',
+        './src/css/profile.less',
+        './src/css/bootswatch-' + bootswatch_theme + '.less'
     ];
 
     var dst = './build/assets/css';
-- 
cgit v1.2.3


From 99f7c4a7cd47bdd670f98d76392a498b6103ebfd Mon Sep 17 00:00:00 2001
From: Camil Staps
Date: Wed, 13 May 2015 17:41:54 +0200
Subject: Different styles structure (relies on gulpfile concatenation); new
 styles added

---
 src/css/bootswatch-lumen.less     | 3 +++
 src/css/bootswatch-superhero.less | 3 +++
 src/css/forms.less                | 4 ++++
 src/css/profile.less              | 5 +++++
 src/css/style.less                | 1 -
 5 files changed, 15 insertions(+), 1 deletion(-)
 create mode 100644 src/css/bootswatch-lumen.less
 create mode 100644 src/css/bootswatch-superhero.less
 create mode 100644 src/css/profile.less
 delete mode 100644 src/css/style.less

diff --git a/src/css/bootswatch-lumen.less b/src/css/bootswatch-lumen.less
new file mode 100644
index 0000000..91e1dcb
--- /dev/null
+++ b/src/css/bootswatch-lumen.less
@@ -0,0 +1,3 @@
+.header {
+    margin-top: 6px;
+}
\ No newline at end of file
diff --git a/src/css/bootswatch-superhero.less b/src/css/bootswatch-superhero.less
new file mode 100644
index 0000000..50e18c8
--- /dev/null
+++ b/src/css/bootswatch-superhero.less
@@ -0,0 +1,3 @@
+.text-muted {
+    color: #abc;
+}
\ No newline at end of file
diff --git a/src/css/forms.less b/src/css/forms.less
index e29f4d7..2a714ce 100644
--- a/src/css/forms.less
+++ b/src/css/forms.less
@@ -6,4 +6,8 @@
         float: right;
         margin-bottom: 0.5em;
     }
+}
+
+form.form-register label {
+    display: block;
 }
\ No newline at end of file
diff --git a/src/css/profile.less b/src/css/profile.less
new file mode 100644
index 0000000..c0b6295
--- /dev/null
+++ b/src/css/profile.less
@@ -0,0 +1,5 @@
+#banner {
+    #banner-email {
+        font-size: 80%;
+    }
+}
\ No newline at end of file
diff --git a/src/css/style.less b/src/css/style.less
deleted file mode 100644
index f32a0b2..0000000
--- a/src/css/style.less
+++ /dev/null
@@ -1 +0,0 @@
-@import 'forms.less';
\ No newline at end of file
-- 
cgit v1.2.3


From 9f3483fccf26e43eed5ccb9945c17cbb7c82a56d Mon Sep 17 00:00:00 2001
From: Camil Staps
Date: Wed, 13 May 2015 17:42:31 +0200
Subject: Fixed BotleaguesFrontend -> Botleagues changes (JS); added profile
 page with different jade base layout

---
 src/404.jade                     |  9 +++++++++
 src/include/layout-loggedin.jade | 32 ++++++++++++++++++++++++++++++++
 src/js/Botleagues.js             | 19 ++++++++++++++++---
 src/js/BotleaguesCallback.js     | 15 +++++++--------
 src/js/BotleaguesFrontend.js     | 30 ++++++++++++------------------
 src/js/forms.js                  |  7 ++++---
 src/js/main.js                   | 26 +++++++++++++++-----------
 src/js/profile.js                | 13 +++++++++++++
 src/profile.jade                 | 12 ++++++++++++
 src/register.jade                | 33 ++++++++++++++++++---------------
 10 files changed, 138 insertions(+), 58 deletions(-)
 create mode 100644 src/404.jade
 create mode 100644 src/include/layout-loggedin.jade
 create mode 100644 src/js/profile.js
 create mode 100644 src/profile.jade

diff --git a/src/404.jade b/src/404.jade
new file mode 100644
index 0000000..65e0aed
--- /dev/null
+++ b/src/404.jade
@@ -0,0 +1,9 @@
+extends ./include/layout-main.jade
+
+block menu
+  -var selected = ''
+
+block content
+  .jumbotron
+    h1 404
+    p.lead Congrats. You did it: you broke my website.
\ No newline at end of file
diff --git a/src/include/layout-loggedin.jade b/src/include/layout-loggedin.jade
new file mode 100644
index 0000000..fca8c17
--- /dev/null
+++ b/src/include/layout-loggedin.jade
@@ -0,0 +1,32 @@
+doctype html
+html(lang="en")
+  head
+    include ./head.jade
+    
+  body
+    .container
+
+      block menu
+        -var selected = '/profile'; //default
+
+      -var menu = { 'Home': '/', 'Leagues': '/leagues', 'My Bots': '/profile/bots', 'Profile': '/profile' };
+
+      .header.clearfix
+        nav: ul.nav.nav-pills.pull-right#nav
+          each val, key in menu
+            if selected === val
+              li.active(role='presentation'): a(href=val,title=key)= key
+            else
+              li(role='presentation'): a(href=val,title=key)= key
+        h3#banner Botleagues
+
+      #messages
+
+      block content
+
+      footer.footer: :markdown
+        &copy; [ViviSoft](http://vivisoft.nl/) 2015
+
+    include ./foot.jade
+
+    block js
\ No newline at end of file
diff --git a/src/js/Botleagues.js b/src/js/Botleagues.js
index 21dd5d7..35c8c0d 100644
--- a/src/js/Botleagues.js
+++ b/src/js/Botleagues.js
@@ -2,6 +2,12 @@ function Botleagues(){}
 
 Botleagues.url = 'https://api.local.botleagues.camilstaps.nl';
 
+$.cookie.json = true;
+Botleagues.cookie_login_email = 'botleagues_login_email';
+Botleagues.cookie_login_user_id = 'botleagues_login_user_id';
+Botleagues.cookie_login_token = 'botleagues_login_token';
+Botleagues.cookie_login_valid_till = 'botleagues_login_valid_till';
+
 Botleagues.request = function(user_options) {
     var callback = user_options.callback;
 
@@ -39,10 +45,17 @@ Botleagues.login = function(email, password) {
         }
     });
 
-    $.cookie(BotleaguesFrontend.cookie_login_email, email);
+    $.cookie(Botleagues.cookie_login_email, email);
 };
 
 Botleagues.logout = function(){
-    BotleaguesFrontend.clearLoginCookies();
-    BotleaguesFrontend.redirect('/');
+    Botleagues.clearLoginCookies();
+    window.location = '/';
+};
+
+Botleagues.clearLoginCookies = function() {
+    $.removeCookie(Botleagues.cookie_login_email);
+    $.removeCookie(Botleagues.cookie_login_user_id);
+    $.removeCookie(Botleagues.cookie_login_token);
+    $.removeCookie(Botleagues.cookie_login_valid_till);
 };
\ No newline at end of file
diff --git a/src/js/BotleaguesCallback.js b/src/js/BotleaguesCallback.js
index b4916c1..13305fa 100644
--- a/src/js/BotleaguesCallback.js
+++ b/src/js/BotleaguesCallback.js
@@ -33,21 +33,20 @@ BotleaguesCallback.register = function(data) {
 
 BotleaguesCallback.login = function(data) {
     if (data.user_token) {
-        BotleaguesFrontend.error({
-            message: "Login successful!",
-            type: 'success'
+        BotleaguesFrontend.success({
+            message: "Login successful!"
         });
         
-        $.cookie(BotleaguesFrontend.cookie_login_user_id, data.user_token.userId);
-        $.cookie(BotleaguesFrontend.cookie_login_token, data.user_token.token);
-        $.cookie(BotleaguesFrontend.cookie_login_valid_till,
+        $.cookie(Botleagues.cookie_login_user_id, data.user_token.userId);
+        $.cookie(Botleagues.cookie_login_token, data.user_token.token);
+        $.cookie(Botleagues.cookie_login_valid_till,
             (new Date()).getTime() + Date.parse(data.user_token.valid_till) - Date.parse(data.user_token.updated_at));
 
-        BotleaguesFrontend.refresh();
+        window.location = '/profile';
     } else {
         BotleaguesFrontend.error({
             message: data.error ? data.error : "Could not login."
         });
-        $.removeCookie(BotleaguesFrontend.cookie_login_email);
+        $.removeCookie(Botleagues.cookie_login_email);
     }
 };
\ No newline at end of file
diff --git a/src/js/BotleaguesFrontend.js b/src/js/BotleaguesFrontend.js
index b94708e..ebc71f2 100644
--- a/src/js/BotleaguesFrontend.js
+++ b/src/js/BotleaguesFrontend.js
@@ -1,16 +1,10 @@
 function BotleaguesFrontend(){}
 
-$.cookie.json = true;
-BotleaguesFrontend.cookie_login_email = 'botleagues_login_email';
-BotleaguesFrontend.cookie_login_user_id = 'botleagues_login_user_id';
-BotleaguesFrontend.cookie_login_token = 'botleagues_login_token';
-BotleaguesFrontend.cookie_login_valid_till = 'botleagues_login_valid_till';
-
-BotleaguesFrontend.error = function(user_options) {
+BotleaguesFrontend.message = function(user_options) {
     options = {
         dismissable: true,
         prepend_to: $('#messages'),
-        type: 'danger'
+        type: 'info'
     };
     for (var key in user_options) {
         options[key] = user_options[key];
@@ -27,17 +21,17 @@ BotleaguesFrontend.error = function(user_options) {
     html.hide().prependTo(options.prepend_to).slideDown().delay(3000).fadeOut().queue(html.remove);
 };
 
-BotleaguesFrontend.refresh = function() {
-    location.reload();
+BotleaguesFrontend.danger = BotleaguesFrontend.error = function(user_options) {
+    user_options.type = 'danger';
+    return BotleaguesFrontend.message(user_options);
 };
 
-BotleaguesFrontend.redirect = function(location) {
-    window.location = location;
-}
+BotleaguesFrontend.success = function(user_options) {
+    user_options.type = 'success';
+    return BotleaguesFrontend.message(user_options);
+};
 
-BotleaguesFrontend.clearLoginCookies = function() {
-    $.removeCookie(BotleaguesFrontend.cookie_login_email);
-    $.removeCookie(BotleaguesFrontend.cookie_login_user_id);
-    $.removeCookie(BotleaguesFrontend.cookie_login_token);
-    $.removeCookie(BotleaguesFrontend.cookie_login_valid_till);
+BotleaguesFrontend.warning = function(user_options) {
+    user_options.type = 'warning';
+    return BotleaguesFrontend.message(user_options);
 };
\ No newline at end of file
diff --git a/src/js/forms.js b/src/js/forms.js
index 6a567a8..8a58b2d 100644
--- a/src/js/forms.js
+++ b/src/js/forms.js
@@ -5,8 +5,9 @@ $('form.form-register').submit(function(){
         data: {
             email: $(this).find('input[name="email"]').val(),
             password: $(this).find('input[name="password"]').val()
-        }
-    }, BotleaguesCallback.register);
+        },
+        callback: BotleaguesCallback.register
+    });
 
     event.preventDefault();
 });
@@ -17,5 +18,5 @@ $('.btn-botleagues-login').focus(function(){
 });
 $('#login-form').submit(function(){
     Botleagues.login($('#login-email').val(), $('#login-password').val());
-    return false;
+    event.preventDefault();
 });
\ No newline at end of file
diff --git a/src/js/main.js b/src/js/main.js
index 4444273..1f869c4 100644
--- a/src/js/main.js
+++ b/src/js/main.js
@@ -1,21 +1,25 @@
 $(document).ready(function(){
 
     // Show profile link instead of login if user is logged in
-    var email = $.cookie(BotleaguesFrontend.cookie_login_email);
-    if (typeof email != 'undefined' && $.cookie(BotleaguesFrontend.cookie_login_valid_till) > (new Date()).getTime()) {
-        setupLoginMenu(email);
+    var email = $.cookie(Botleagues.cookie_login_email);
+    if (typeof email != 'undefined' && $.cookie(Botleagues.cookie_login_valid_till) > (new Date()).getTime()) {
+        setupLoginMenu();
     }
 });
 
-function setupLoginMenu(email) {
+function setupLoginMenu() {
     $('#nav .login-link').remove();
-    $('<li>').append(
-        $('<a>')
-            .attr('role', 'presentation')
-            .attr('title', 'User profile')
-            .attr('href', '/profile')
-            .text(email))
-        .appendTo($('#nav'));
+    
+    if ($('#nav').find('[href="/profile"]').length == 0) {
+        $('<li>').append(
+            $('<a>')
+                .attr('role', 'presentation')
+                .attr('title', 'User profile')
+                .attr('href', '/profile')
+                .text('Profile'))
+            .appendTo($('#nav'));
+    }
+    
     $('<li>').append(
         $('<a>')
             .attr('role', 'presentation')
diff --git a/src/js/profile.js b/src/js/profile.js
new file mode 100644
index 0000000..48600db
--- /dev/null
+++ b/src/js/profile.js
@@ -0,0 +1,13 @@
+$(document).ready(function(){
+    setupGreeter();
+});
+
+function setupGreeter() {
+    $('#greeter').append(' ' + $.cookie(Botleagues.cookie_login_email));
+    $('#banner').append(
+        $('<span>')
+            .attr('id', 'banner-email')
+            .addClass('text-muted')
+            .text(' / ' + $.cookie(Botleagues.cookie_login_email))
+    );
+}
\ No newline at end of file
diff --git a/src/profile.jade b/src/profile.jade
new file mode 100644
index 0000000..568434c
--- /dev/null
+++ b/src/profile.jade
@@ -0,0 +1,12 @@
+extends ./include/layout-loggedin.jade
+
+block menu
+  -var selected = '/profile'
+
+block content
+  .jumbotron
+    h1 Welcome back
+    p.lead#greeter You're logged in as
+
+block js
+  script(src='/assets/js/profile.js', type='text/javascript')
\ No newline at end of file
diff --git a/src/register.jade b/src/register.jade
index 8f79715..b373d1c 100644
--- a/src/register.jade
+++ b/src/register.jade
@@ -6,21 +6,24 @@ block menu
 block content
   .row
     .col-lg-6
-      h4 Register
-      form.form-register(action='#')
-        .form-group
-          label(for="register-email") Email
-          input.form-control#register-email(type='email',name='email',placeholder="Enter email")
-        .form-group
-          label(for="register-password") Password
-          input.form-control#register-password(type='password',name='password',placeholder="Enter password")
-        .form-group
-          label(for="register-password2") Password (confirmation)
-          input.form-control#register-password2(type='password',name='password',placeholder="Enter password again")
-        .checkbox: label
-          input#accepts-toc(type='checkbox',name="accepts-toc")
-          | I accept the terms and conditions
-        button.btn.btn-lg.btn-success.pull-right(type='submit') Register
+      div.well.bs-component
+        h4 Register
+        form.form-register(action='#')
+          .form-group
+            label(for="register-email") Email
+            input.form-control#register-email(type='email',name='email',placeholder="Enter email")
+          .form-group
+            label(for="register-password") Password
+            input.form-control#register-password(type='password',name='password',placeholder="Enter password")
+          .form-group
+            label(for="register-password2") Password (confirmation)
+            input.form-control#register-password2(type='password',name='password',placeholder="Enter password again")
+          .checkbox: label
+            input#accepts-toc(type='checkbox',name="accepts-toc")
+            | I accept the terms and conditions
+          button.btn.btn-lg.btn-success.pull-right(type='submit') Register
+          br(style='clear:both;')
+
     .col-lg-6
       h4 Subheading
       p Donec id elit non mi porta gravida at eget metus. Maecenas faucibus mollis interdum.
-- 
cgit v1.2.3


From e7b060dbe94e4bf67dd127cc063ef948fe449201 Mon Sep 17 00:00:00 2001
From: Camil Staps
Date: Wed, 13 May 2015 18:07:46 +0200
Subject: Faster gulpfile

---
 gulpfile.js | 21 ++++++++++++---------
 1 file changed, 12 insertions(+), 9 deletions(-)

diff --git a/gulpfile.js b/gulpfile.js
index 9bd83f8..868e3ff 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -30,7 +30,7 @@ gulp.task('default', [], function() {
 });
 
 gulp.task('all', [], function() {
-    gulp.start('fonts', 'styles', 'scripts', 'images', 'jade', '3rd-party-styles');
+    gulp.start('fonts', 'styles', 'scripts', 'images', 'jade', '3rd-party-styles', '3rd-party-scripts');
 });
 
 gulp.task('rebuild', ['clean'], function() {
@@ -130,11 +130,11 @@ gulp.task('styles', function() {
         .pipe(changed(dst, {destination: dst_filename}))
         .pipe(less())
         .pipe(concat(dst_filename))
-        .pipe(minifycss())
+        .pipe(gulpif(production, minifycss()))
         .pipe(gulp.dest(dst));
 });
 
-gulp.task('scripts', function(){
+gulp.task('3rd-party-scripts', function(){
     var fileList = [
         './bower_components/jquery/dist/jquery.min.js',
         './bower_components/bootstrap/dist/js/bootstrap.min.js',
@@ -143,19 +143,22 @@ gulp.task('scripts', function(){
 
     var dst = './build/assets/js';
 
-    gulp.src(fileList)
+    return gulp.src(fileList)
         .pipe(changed(dst, {destination: 'script.js'}))
         .pipe(concat('script.js'))
         .pipe(stripdebug())
         .pipe(uglify())
         .pipe(gulp.dest(dst));
+});
 
+gulp.task('scripts', function(){
     var src = './src/js/*.js';
+    var dst = './build/assets/js';
 
-    gulp.src(src)
+    return gulp.src(src)
         .pipe(changed(dst))
         .pipe(gulpif(production, stripdebug()))
-        .pipe(uglify())
+        .pipe(gulpif(production, uglify()))
         .pipe(gulp.dest(dst));
 });
 
@@ -163,7 +166,7 @@ gulp.task('images', function(){
     var src = './src/img/**/*',
         dst = './build/img';
 
-    gulp.src(src)
+    return gulp.src(src)
         .pipe(changed(dst))
         .pipe(imagemin())
         .pipe(gulp.dest(dst));
@@ -173,10 +176,10 @@ gulp.task('jade', function(){
     var src = './src/*.jade',
         dst = './build';
 
-    gulp.src(src)
+    return gulp.src(src)
         .pipe(changed(dst, {extension: 'html'}))
         .pipe(jade())
-        .pipe(minifyhtml())
+        .pipe(gulpif(production, minifyhtml()))
         .pipe(gulp.dest(dst));
 });
 
-- 
cgit v1.2.3


From 744ca0f344e28e5770f9c164fd9fac5579f23cc6 Mon Sep 17 00:00:00 2001
From: Camil Staps
Date: Wed, 13 May 2015 18:08:15 +0200
Subject: Remove layout-loggedin, add extra links to nav when logged in

---
 src/include/layout-loggedin.jade | 32 --------------------------------
 src/include/layout-main.jade     |  2 ++
 src/js/main.js                   | 27 ++++++++++++---------------
 src/js/profile.js                |  1 +
 src/profile.jade                 |  2 +-
 5 files changed, 16 insertions(+), 48 deletions(-)
 delete mode 100644 src/include/layout-loggedin.jade

diff --git a/src/include/layout-loggedin.jade b/src/include/layout-loggedin.jade
deleted file mode 100644
index fca8c17..0000000
--- a/src/include/layout-loggedin.jade
+++ /dev/null
@@ -1,32 +0,0 @@
-doctype html
-html(lang="en")
-  head
-    include ./head.jade
-    
-  body
-    .container
-
-      block menu
-        -var selected = '/profile'; //default
-
-      -var menu = { 'Home': '/', 'Leagues': '/leagues', 'My Bots': '/profile/bots', 'Profile': '/profile' };
-
-      .header.clearfix
-        nav: ul.nav.nav-pills.pull-right#nav
-          each val, key in menu
-            if selected === val
-              li.active(role='presentation'): a(href=val,title=key)= key
-            else
-              li(role='presentation'): a(href=val,title=key)= key
-        h3#banner Botleagues
-
-      #messages
-
-      block content
-
-      footer.footer: :markdown
-        &copy; [ViviSoft](http://vivisoft.nl/) 2015
-
-    include ./foot.jade
-
-    block js
\ No newline at end of file
diff --git a/src/include/layout-main.jade b/src/include/layout-main.jade
index 4b521a9..c17a841 100644
--- a/src/include/layout-main.jade
+++ b/src/include/layout-main.jade
@@ -38,6 +38,8 @@ html(lang="en")
       footer.footer: :markdown
         &copy; [ViviSoft](http://vivisoft.nl/) 2015
 
+    script(type='text/javascript')!= 'var selected_page = "' + selected + '";'
+
     include ./foot.jade
 
     block js
\ No newline at end of file
diff --git a/src/js/main.js b/src/js/main.js
index 1f869c4..5d17e02 100644
--- a/src/js/main.js
+++ b/src/js/main.js
@@ -9,22 +9,19 @@ $(document).ready(function(){
 
 function setupLoginMenu() {
     $('#nav .login-link').remove();
-    
-    if ($('#nav').find('[href="/profile"]').length == 0) {
-        $('<li>').append(
+
+    var extra_links = {'Leagues': '/leagues', 'My Bots': '/profile/bots', 'Profile': '/profile', 'Logout': '/logout'};
+
+    for (var text in extra_links) {
+        var li = $('<li>').append(
             $('<a>')
                 .attr('role', 'presentation')
-                .attr('title', 'User profile')
-                .attr('href', '/profile')
-                .text('Profile'))
-            .appendTo($('#nav'));
+                .attr('title', text)
+                .attr('href', extra_links[text])
+                .text(text));
+        if (extra_links[text] == selected_page) { // selected_page is added in layout-main.jade
+            li.addClass('active');
+        }
+        li.appendTo($('#nav'));
     }
-    
-    $('<li>').append(
-        $('<a>')
-            .attr('role', 'presentation')
-            .attr('title', 'Logout')
-            .attr('href', '/logout')
-            .text('Logout'))
-        .appendTo($('#nav'));
 }
\ No newline at end of file
diff --git a/src/js/profile.js b/src/js/profile.js
index 48600db..7b36432 100644
--- a/src/js/profile.js
+++ b/src/js/profile.js
@@ -4,6 +4,7 @@ $(document).ready(function(){
 
 function setupGreeter() {
     $('#greeter').append(' ' + $.cookie(Botleagues.cookie_login_email));
+    
     $('#banner').append(
         $('<span>')
             .attr('id', 'banner-email')
diff --git a/src/profile.jade b/src/profile.jade
index 568434c..9f68f60 100644
--- a/src/profile.jade
+++ b/src/profile.jade
@@ -1,4 +1,4 @@
-extends ./include/layout-loggedin.jade
+extends ./include/layout-main.jade
 
 block menu
   -var selected = '/profile'
-- 
cgit v1.2.3


From 10e78614c7c00024f8b10bd5a982e2b46b5d6a74 Mon Sep 17 00:00:00 2001
From: Camil Staps
Date: Wed, 13 May 2015 18:24:15 +0200
Subject: Cleaner jade

---
 src/404.jade                 |  8 ++++----
 src/about.jade               |  4 ++++
 src/css/profile.less         |  6 ++----
 src/include/layout-main.jade | 22 ++++++++++++++++++++++
 src/index.jade               | 14 ++++++++------
 src/js/BotleaguesCallback.js |  4 ++--
 src/js/profile.js            |  4 ++--
 src/logout.jade              |  2 +-
 src/profile.jade             |  8 ++++----
 src/register.jade            | 13 ++++---------
 10 files changed, 53 insertions(+), 32 deletions(-)

diff --git a/src/404.jade b/src/404.jade
index 65e0aed..172c126 100644
--- a/src/404.jade
+++ b/src/404.jade
@@ -3,7 +3,7 @@ extends ./include/layout-main.jade
 block menu
   -var selected = ''
 
-block content
-  .jumbotron
-    h1 404
-    p.lead Congrats. You did it: you broke my website.
\ No newline at end of file
+block header
+  -var header_jumbotron = true
+  -var header_title = '404'
+  -var header_subtitle = 'Congrats. You did it: you broke my website.'
\ No newline at end of file
diff --git a/src/about.jade b/src/about.jade
index 2c424d4..0ae837d 100644
--- a/src/about.jade
+++ b/src/about.jade
@@ -3,6 +3,10 @@ extends ./include/layout-main.jade
 block menu
   -var selected = '/about'
 
+block header
+  -var header_jumbotron = false
+  -var header_title = 'About'
+
 block content
   .row
     .col-lg-6
diff --git a/src/css/profile.less b/src/css/profile.less
index c0b6295..85d708c 100644
--- a/src/css/profile.less
+++ b/src/css/profile.less
@@ -1,5 +1,3 @@
-#banner {
-    #banner-email {
-        font-size: 80%;
-    }
+#banner-email {
+    font-size: 80%;
 }
\ No newline at end of file
diff --git a/src/include/layout-main.jade b/src/include/layout-main.jade
index c17a841..abbb466 100644
--- a/src/include/layout-main.jade
+++ b/src/include/layout-main.jade
@@ -27,12 +27,34 @@ html(lang="en")
         form.form-inline#login-form(action='#',method='post')
           .form-group
             input.form-control#login-email(type='email',placeholder='Email')
+          | &nbsp;
           .form-group
             input.form-control#login-password(type='password',placeholder='Password')
+          | &nbsp;
           .form-group
             button.btn.btn-default.pull-right#login-submit(role='submit') Login
         br(style='clear:both;')
 
+      -var header_jumbotron = false
+      block header
+
+      -if (header_jumbotron)
+        .jumbotron
+          h1= header_title
+          -if (header_subtitle)
+            p.lead= header_subtitle
+          p.row
+            block header_content
+      -else
+        .row
+          .col-lg-12
+            .bs-component
+              h1= header_title
+              -if (header_subtitle)
+                p.lead= header_subtitle
+              p.row
+                block header_content
+
       block content
 
       footer.footer: :markdown
diff --git a/src/index.jade b/src/index.jade
index 6b6a175..a9e7ef5 100644
--- a/src/index.jade
+++ b/src/index.jade
@@ -3,13 +3,15 @@ extends ./include/layout-main.jade
 block menu
   -var selected = '/'
 
-block content
-  .jumbotron
-    h1 Welcome
-    p.lead Botleagues: write Java bots for different games, join competitions and win prizes!
-    p.row
-      a.btn.btn-lg.btn-success.pull-right(href='/register', role='button') Register now
+block header
+  -var header_jumbotron = true
+  -var header_title = 'Welcome'
+  -var header_subtitle = 'Botleagues: write Java bots for different games, join competitions and win prizes!'
+
+block header_content
+  a.btn.btn-lg.btn-success.pull-right(href='/register', role='button') Register now
 
+block content
   .row
     .col-lg-4
       h4 Subheading
diff --git a/src/js/BotleaguesCallback.js b/src/js/BotleaguesCallback.js
index 13305fa..ff99225 100644
--- a/src/js/BotleaguesCallback.js
+++ b/src/js/BotleaguesCallback.js
@@ -34,7 +34,7 @@ BotleaguesCallback.register = function(data) {
 BotleaguesCallback.login = function(data) {
     if (data.user_token) {
         BotleaguesFrontend.success({
-            message: "Login successful!"
+            message: "Login successful! Refreshing the page..."
         });
         
         $.cookie(Botleagues.cookie_login_user_id, data.user_token.userId);
@@ -42,7 +42,7 @@ BotleaguesCallback.login = function(data) {
         $.cookie(Botleagues.cookie_login_valid_till,
             (new Date()).getTime() + Date.parse(data.user_token.valid_till) - Date.parse(data.user_token.updated_at));
 
-        window.location = '/profile';
+        window.setTimeout(function(){ window.location = '/profile'; }, 1000);
     } else {
         BotleaguesFrontend.error({
             message: data.error ? data.error : "Could not login."
diff --git a/src/js/profile.js b/src/js/profile.js
index 7b36432..f27e562 100644
--- a/src/js/profile.js
+++ b/src/js/profile.js
@@ -3,9 +3,9 @@ $(document).ready(function(){
 });
 
 function setupGreeter() {
-    $('#greeter').append(' ' + $.cookie(Botleagues.cookie_login_email));
+    $('.jumbotron .lead').append(' ' + $.cookie(Botleagues.cookie_login_email));
     
-    $('#banner').append(
+    $('.header h3').append(
         $('<span>')
             .attr('id', 'banner-email')
             .addClass('text-muted')
diff --git a/src/logout.jade b/src/logout.jade
index f94e608..d19e44a 100644
--- a/src/logout.jade
+++ b/src/logout.jade
@@ -4,7 +4,7 @@ block menu
   -var selected = '/logout'
 
 block content
-  p Login you out...
+  p Logging you out...
 
 block js
   script(type='text/javascript')
diff --git a/src/profile.jade b/src/profile.jade
index 9f68f60..5b97b30 100644
--- a/src/profile.jade
+++ b/src/profile.jade
@@ -3,10 +3,10 @@ extends ./include/layout-main.jade
 block menu
   -var selected = '/profile'
 
-block content
-  .jumbotron
-    h1 Welcome back
-    p.lead#greeter You're logged in as
+block header
+  -var header_jumbotron = true
+  -var header_title = 'Welcome back'
+  -var header_subtitle = "You're logged in as"
 
 block js
   script(src='/assets/js/profile.js', type='text/javascript')
\ No newline at end of file
diff --git a/src/register.jade b/src/register.jade
index b373d1c..ca8cc83 100644
--- a/src/register.jade
+++ b/src/register.jade
@@ -3,6 +3,9 @@ extends ./include/layout-main.jade
 block menu
   -var selected = '/register'
 
+block header
+  -var header_title = 'Register'
+
 block content
   .row
     .col-lg-6
@@ -22,12 +25,4 @@ block content
             input#accepts-toc(type='checkbox',name="accepts-toc")
             | I accept the terms and conditions
           button.btn.btn-lg.btn-success.pull-right(type='submit') Register
-          br(style='clear:both;')
-
-    .col-lg-6
-      h4 Subheading
-      p Donec id elit non mi porta gravida at eget metus. Maecenas faucibus mollis interdum.
-      h4 Subheading
-      p Morbi leo risus, porta ac consectetur ac, vestibulum at eros. Cras mattis consectetur purus sit amet fermentum.
-      h4 Subheading
-      p Maecenas sed diam eget risus varius blandit sit amet non magna.
\ No newline at end of file
+          br(style='clear:both;')
\ No newline at end of file
-- 
cgit v1.2.3


From 05cd09f12da313207fb2eb031982b3a15a4f843f Mon Sep 17 00:00:00 2001
From: Camil Staps
Date: Wed, 13 May 2015 18:44:04 +0200
Subject: Link in header on 'Botleagues'; About page

---
 gulpfile.js                  |  1 +
 src/about.jade               | 24 ++++++++++--------------
 src/css/general.less         |  4 ++++
 src/include/layout-main.jade |  4 ++--
 src/logout.jade              |  3 +--
 5 files changed, 18 insertions(+), 18 deletions(-)
 create mode 100644 src/css/general.less

diff --git a/gulpfile.js b/gulpfile.js
index 868e3ff..96768e7 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -119,6 +119,7 @@ gulp.task('styles', function() {
     
     var sources = [
         './src/css/forms.less',
+        './src/css/general.less',
         './src/css/profile.less',
         './src/css/bootswatch-' + bootswatch_theme + '.less'
     ];
diff --git a/src/about.jade b/src/about.jade
index 0ae837d..7781682 100644
--- a/src/about.jade
+++ b/src/about.jade
@@ -9,17 +9,13 @@ block header
 
 block content
   .row
-    .col-lg-6
-      h4 Subheading
-      p Donec id elit non mi porta gravida at eget metus. Maecenas faucibus mollis interdum.
-      h4 Subheading
-      p Morbi leo risus, porta ac consectetur ac, vestibulum at eros. Cras mattis consectetur purus sit amet fermentum.
-      h4 Subheading
-      p Maecenas sed diam eget risus varius blandit sit amet non magna.
-    .col-lg-6
-      h4 Subheading
-      p Donec id elit non mi porta gravida at eget metus. Maecenas faucibus mollis interdum.
-      h4 Subheading
-      p Morbi leo risus, porta ac consectetur ac, vestibulum at eros. Cras mattis consectetur purus sit amet fermentum.
-      h4 Subheading
-      p Maecenas sed diam eget risus varius blandit sit amet non magna.
\ No newline at end of file
+    .col-lg-12: :markdown
+      Botleagues is an open source software solution with three aspects:
+      
+      * A Game Controller that lets software bots play games against each other (handled by Java)
+      * A semi-RESTful API that allows users to register, create competitions and play against other bots (with Laravel 4.2 and Dingo API)
+      * A front-end to the API (entirely client-side code, using Bootstrap and jade)
+      
+      You may find more information on [GitHub](https://github.com/camilstaps/Botleagues).
+
+      If you wish to contact the developers, please consider adding an issue on GitHub. If that's not what you want: you can reach us at info [at] camilstaps [dot] nl.
\ No newline at end of file
diff --git a/src/css/general.less b/src/css/general.less
new file mode 100644
index 0000000..1218018
--- /dev/null
+++ b/src/css/general.less
@@ -0,0 +1,4 @@
+a.no-style {
+    color: inherit !important;
+    text-decoration: inherit !important;
+}
\ No newline at end of file
diff --git a/src/include/layout-main.jade b/src/include/layout-main.jade
index abbb466..12c283e 100644
--- a/src/include/layout-main.jade
+++ b/src/include/layout-main.jade
@@ -9,7 +9,7 @@ html(lang="en")
       block menu
         -var selected = '/'; //default
 
-      -var menu = { 'Home': '/', 'About': '/about', 'Contact': '/contact' };
+      -var menu = { 'Home': '/', 'About': '/about' };
 
       .header.clearfix
         nav: ul.nav.nav-pills.pull-right#nav
@@ -19,7 +19,7 @@ html(lang="en")
             else
               li(role='presentation'): a(href=val,title=key)= key
           li.login-link(role='presentation'): a.btn-botleagues-login(href='#',title='Login') Login
-        h3 Botleagues
+        h3: a.no-style(href='/') Botleagues
 
       #messages
 
diff --git a/src/logout.jade b/src/logout.jade
index d19e44a..14c9aac 100644
--- a/src/logout.jade
+++ b/src/logout.jade
@@ -7,5 +7,4 @@ block content
   p Logging you out...
 
 block js
-  script(type='text/javascript')
-    |$(document).ready(function(){ Botleagues.logout(); });
\ No newline at end of file
+  script(type='text/javascript') $(document).ready(function(){ Botleagues.logout(); });
\ No newline at end of file
-- 
cgit v1.2.3


From a14b49e59e6764b6b7764ee3bc95d0d049bf21f8 Mon Sep 17 00:00:00 2001
From: Camil Staps
Date: Wed, 13 May 2015 22:57:53 +0200
Subject: Turned javascript into coffeescript

---
 gulpfile.js                      | 10 +++++--
 package.json                     |  1 +
 src/js/Botleagues.coffee         | 54 +++++++++++++++++++++++++++++++++++
 src/js/Botleagues.js             | 61 ----------------------------------------
 src/js/BotleaguesCallback.coffee | 52 ++++++++++++++++++++++++++++++++++
 src/js/BotleaguesCallback.js     | 52 ----------------------------------
 src/js/BotleaguesFrontend.coffee | 42 +++++++++++++++++++++++++++
 src/js/BotleaguesFrontend.js     | 37 ------------------------
 src/js/forms.coffee              | 25 ++++++++++++++++
 src/js/forms.js                  | 22 ---------------
 src/js/main.coffee               | 29 +++++++++++++++++++
 src/js/main.js                   | 27 ------------------
 src/js/profile.coffee            | 15 ++++++++++
 src/js/profile.js                | 14 ---------
 14 files changed, 226 insertions(+), 215 deletions(-)
 create mode 100644 src/js/Botleagues.coffee
 delete mode 100644 src/js/Botleagues.js
 create mode 100644 src/js/BotleaguesCallback.coffee
 delete mode 100644 src/js/BotleaguesCallback.js
 create mode 100644 src/js/BotleaguesFrontend.coffee
 delete mode 100644 src/js/BotleaguesFrontend.js
 create mode 100644 src/js/forms.coffee
 delete mode 100644 src/js/forms.js
 create mode 100644 src/js/main.coffee
 delete mode 100644 src/js/main.js
 create mode 100644 src/js/profile.coffee
 delete mode 100644 src/js/profile.js

diff --git a/gulpfile.js b/gulpfile.js
index 96768e7..4a0dff1 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -2,6 +2,7 @@
 
 var gulp = require('gulp'),
     changed = require('gulp-changed'),
+    coffee = require('gulp-coffee'),
     concat = require('gulp-concat'),
     debug = require('gulp-debug'),
     foreach = require('gulp-foreach'),
@@ -153,11 +154,16 @@ gulp.task('3rd-party-scripts', function(){
 });
 
 gulp.task('scripts', function(){
-    var src = './src/js/*.js';
+    var src = [
+        './src/js/*.js',
+        './src/js/*.coffee'
+    ]
+    ;
     var dst = './build/assets/js';
 
     return gulp.src(src)
-        .pipe(changed(dst))
+        .pipe(changed(dst, { extension: 'js' }))
+        .pipe(gulpif(/\.coffee$/, coffee()))
         .pipe(gulpif(production, stripdebug()))
         .pipe(gulpif(production, uglify()))
         .pipe(gulp.dest(dst));
diff --git a/package.json b/package.json
index d5c122a..61bf2fe 100644
--- a/package.json
+++ b/package.json
@@ -9,6 +9,7 @@
     "gulp": "^3.8.11",
     "gulp-autoprefixer": "^2.1.0",
     "gulp-changed": "~1.2.1",
+    "gulp-coffee": "~2.3.1",
     "gulp-concat": "~2.5.2",
     "gulp-debug": "^2.0.0",
     "gulp-foreach": "^0.1.0",
diff --git a/src/js/Botleagues.coffee b/src/js/Botleagues.coffee
new file mode 100644
index 0000000..06ace76
--- /dev/null
+++ b/src/js/Botleagues.coffee
@@ -0,0 +1,54 @@
+$.cookie.json = true
+
+@Botleagues =
+
+    url: 'https://api.local.botleagues.camilstaps.nl'
+
+    cookie_login_email: 'botleagues_login_email'
+    cookie_login_user_id: 'botleagues_login_user_id'
+    cookie_login_token: 'botleagues_login_token'
+    cookie_login_valid_till: 'botleagues_login_valid_till'
+
+    request: (user_options) ->
+        callback = user_options.callback
+
+        options =
+            method: 'GET'
+            dataType: 'json'
+            complete: (data) ->
+                callback data.responseJSON
+
+        url = Botleagues.url + '/' + user_options.endpoint
+        delete user_options.callback
+        delete user_options.endpoint
+
+        for key, option of user_options
+            options[key] = option
+
+        jQuery.ajax url, options
+
+        return
+
+    login: (email, password) ->
+        Botleagues.request
+            endpoint: 'user_token'
+            method: 'POST'
+            callback: BotleaguesCallback.login
+            headers:
+                'Authorization': 'Basic ' + btoa(email + ':' + password)
+
+        $.cookie Botleagues.cookie_login_email, email
+
+        return
+
+    logout: ->
+        Botleagues.clearLoginCookies()
+        window.location = '/'
+        return
+
+    clearLoginCookies: ->
+        $.removeCookie Botleagues.cookie_login_email
+        $.removeCookie Botleagues.cookie_login_user_id
+        $.removeCookie Botleagues.cookie_login_token
+        $.removeCookie Botleagues.cookie_login_valid_till
+        return
\ No newline at end of file
diff --git a/src/js/Botleagues.js b/src/js/Botleagues.js
deleted file mode 100644
index 35c8c0d..0000000
--- a/src/js/Botleagues.js
+++ /dev/null
@@ -1,61 +0,0 @@
-function Botleagues(){}
-
-Botleagues.url = 'https://api.local.botleagues.camilstaps.nl';
-
-$.cookie.json = true;
-Botleagues.cookie_login_email = 'botleagues_login_email';
-Botleagues.cookie_login_user_id = 'botleagues_login_user_id';
-Botleagues.cookie_login_token = 'botleagues_login_token';
-Botleagues.cookie_login_valid_till = 'botleagues_login_valid_till';
-
-Botleagues.request = function(user_options) {
-    var callback = user_options.callback;
-
-    var options = {
-        endpoint: null,
-        method: 'GET',
-        dataType: 'json',
-        complete: function(data) {
-            callback(data.responseJSON);
-        }
-    };
-
-    var url = Botleagues.url + '/' + user_options['endpoint'];
-    delete user_options['callback'];
-    delete user_options['endpoint'];
-
-    for (var name in user_options) {
-        options[name] = user_options[name];
-    }
-
-    jQuery.ajax(url, options);
-};
-
-Botleagues.redirect = function(user_options) {
-    window.location = Botleagues.url + '/' + user_options['endpoint'];
-};
-
-Botleagues.login = function(email, password) {
-    Botleagues.request({
-        endpoint: 'user_token',
-        method: 'POST',
-        callback: BotleaguesCallback.login,
-        headers: {
-            'Authorization': 'Basic ' + btoa(email + ':' + password)
-        }
-    });
-
-    $.cookie(Botleagues.cookie_login_email, email);
-};
-
-Botleagues.logout = function(){
-    Botleagues.clearLoginCookies();
-    window.location = '/';
-};
-
-Botleagues.clearLoginCookies = function() {
-    $.removeCookie(Botleagues.cookie_login_email);
-    $.removeCookie(Botleagues.cookie_login_user_id);
-    $.removeCookie(Botleagues.cookie_login_token);
-    $.removeCookie(Botleagues.cookie_login_valid_till);
-};
\ No newline at end of file
diff --git a/src/js/BotleaguesCallback.coffee b/src/js/BotleaguesCallback.coffee
new file mode 100644
index 0000000..a02ee59
--- /dev/null
+++ b/src/js/BotleaguesCallback.coffee
@@ -0,0 +1,52 @@
+@BotleaguesCallback =
+
+    register: (data) ->
+        $ 'form.form-register .form-group'
+            .removeClass 'has-feedback has-success has-warning has-error'
+            .find '.form-control-feedback'
+            .remove()
+
+        if data.error?
+            BotleaguesFrontend.error
+                message: data.error
+                prepend_to: $ 'form.form-register'
+
+            for key, msgs of data.errors
+                error_msg = msgs.join '; '
+
+                $('#register-' + key)
+                    .attr 'title', error_msg
+                    .parent()
+                    .addClass 'has-feedback has-error'
+                    .append(
+                        $ '<span>'
+                            .addClass 'glyphicon glyphicon-remove form-control-feedback'
+                            .attr 'aria-hidden', true
+                    )
+                    .find 'label'
+                    .append(
+                        $ '<span>'
+                            .addClass 'pull-right text-danger'
+                            .text error_msg
+                    )
+
+        return
+
+    login: (data) ->
+        if data.user_token?
+            BotleaguesFrontend.success
+                message: 'Login successful! Refreshing the page...'
+
+            $.cookie Botleagues.cookie_login_user_id, data.user_token.userId
+            $.cookie Botleagues.cookie_login_token, data.user_token.token
+            $.cookie Botleagues.cookie_login_valid_till, (new Date()).getTime() + Date.parse(data.user_token.valid_till) - Date.parse(data.user_token.updated_at)
+
+            window.setTimeout (-> window.location = 'profile'), 1000
+
+        else
+            BotleaguesFrontend.error
+                message: if data.error? then data.error else "Could not login."
+
+            $.removeCookie Botleagues.cookie_login_email
+
+        return
\ No newline at end of file
diff --git a/src/js/BotleaguesCallback.js b/src/js/BotleaguesCallback.js
deleted file mode 100644
index ff99225..0000000
--- a/src/js/BotleaguesCallback.js
+++ /dev/null
@@ -1,52 +0,0 @@
-function BotleaguesCallback(){}
-
-BotleaguesCallback.register = function(data) {
-    $('form.form-register .form-group')
-        .removeClass('has-feedback has-success has-warning, has-error')
-        .find('.form-control-feedback').remove();
-
-    if (typeof data.error !== 'undefined') {
-        BotleaguesFrontend.error({message: data.error, prepend_to: $('form.form-register')});
-        if (typeof data.errors !== 'undefined') {
-            for (var key in data.errors) {
-                var error_msg = data.errors[key].join('; ');
-
-                $('#register-' + key)
-                    .attr('title', error_msg)
-                    .parent()
-                    .addClass('has-feedback has-error')
-                    .append(
-                        $('<span>')
-                            .addClass('glyphicon glyphicon-remove form-control-feedback')
-                            .attr('aria-hidden', true)
-                    )
-                    .find('label')
-                    .append(
-                        $('<span>')
-                            .addClass('pull-right text-danger')
-                            .text(error_msg)
-                    );
-            }
-        }
-    }
-};
-
-BotleaguesCallback.login = function(data) {
-    if (data.user_token) {
-        BotleaguesFrontend.success({
-            message: "Login successful! Refreshing the page..."
-        });
-        
-        $.cookie(Botleagues.cookie_login_user_id, data.user_token.userId);
-        $.cookie(Botleagues.cookie_login_token, data.user_token.token);
-        $.cookie(Botleagues.cookie_login_valid_till,
-            (new Date()).getTime() + Date.parse(data.user_token.valid_till) - Date.parse(data.user_token.updated_at));
-
-        window.setTimeout(function(){ window.location = '/profile'; }, 1000);
-    } else {
-        BotleaguesFrontend.error({
-            message: data.error ? data.error : "Could not login."
-        });
-        $.removeCookie(Botleagues.cookie_login_email);
-    }
-};
\ No newline at end of file
diff --git a/src/js/BotleaguesFrontend.coffee b/src/js/BotleaguesFrontend.coffee
new file mode 100644
index 0000000..5c2d116
--- /dev/null
+++ b/src/js/BotleaguesFrontend.coffee
@@ -0,0 +1,42 @@
+@BotleaguesFrontend =
+    
+    message: (user_options) ->
+        options =
+            dismissable: true
+            prepend_to: $ '#messages'
+            type: 'info'
+
+        for key, option of user_options
+            options[key] = option
+
+        html = '<div class="alert alert-' + options.type + '">'
+        if options.dismissable
+            html += '<a href="#" class="close" data-dismiss="alert">&times;</a>'
+        html += options.message
+        html += '</div>'
+
+        html = $ html
+        html
+            .hide()
+            .prependTo options.prepend_to
+            .slideDown()
+            .delay 3000
+            .fadeOut()
+            .queue html.remove
+
+        return
+
+    error: (user_options) ->
+        user_options.type = 'danger'
+        BotleaguesFrontend.message user_options
+
+    danger: (user_options) ->
+        BotleaguesFrontend.error user_options
+
+    success: (user_options) ->
+        user_options.type = 'success'
+        BotleaguesFrontend.message user_options
+
+    warning: (user_options) ->
+        user_options.type = 'warning'
+        BotleaguesFrontend.message user_options
\ No newline at end of file
diff --git a/src/js/BotleaguesFrontend.js b/src/js/BotleaguesFrontend.js
deleted file mode 100644
index ebc71f2..0000000
--- a/src/js/BotleaguesFrontend.js
+++ /dev/null
@@ -1,37 +0,0 @@
-function BotleaguesFrontend(){}
-
-BotleaguesFrontend.message = function(user_options) {
-    options = {
-        dismissable: true,
-        prepend_to: $('#messages'),
-        type: 'info'
-    };
-    for (var key in user_options) {
-        options[key] = user_options[key];
-    }
-
-    var html = '<div class="alert alert-' + options.type + '">';
-    if (options.dismissable === true)
-        html += '<a href="#" class="close" data-dismiss="alert">&times;</a>';
-    html += options.message;
-    html += '</div>';
-
-    html = $(html);
-
-    html.hide().prependTo(options.prepend_to).slideDown().delay(3000).fadeOut().queue(html.remove);
-};
-
-BotleaguesFrontend.danger = BotleaguesFrontend.error = function(user_options) {
-    user_options.type = 'danger';
-    return BotleaguesFrontend.message(user_options);
-};
-
-BotleaguesFrontend.success = function(user_options) {
-    user_options.type = 'success';
-    return BotleaguesFrontend.message(user_options);
-};
-
-BotleaguesFrontend.warning = function(user_options) {
-    user_options.type = 'warning';
-    return BotleaguesFrontend.message(user_options);
-};
\ No newline at end of file
diff --git a/src/js/forms.coffee b/src/js/forms.coffee
new file mode 100644
index 0000000..e742160
--- /dev/null
+++ b/src/js/forms.coffee
@@ -0,0 +1,25 @@
+# Request API for registering
+$('form.form-register').submit ->
+    Botleagues.request
+        endpoint: 'user'
+        method: 'POST'
+        data:
+            email: $(this).find('input[name="email"]').val()
+            password: $(this).find('input[name="password"]').val()
+        callback: BotleaguesCallback.register
+
+    event.preventDefault()
+
+    return
+
+# Show login form on click
+$('.btn-botleagues-login').focus ->
+    $('#login-block').slideDown()
+    $('#login-email').focus()
+    return
+
+# Request API for logging in
+$('#login-form').submit ->
+    Botleagues.login $('#login-email').val(), $('#login-password').val()
+    event.preventDefault()
+    return
\ No newline at end of file
diff --git a/src/js/forms.js b/src/js/forms.js
deleted file mode 100644
index 8a58b2d..0000000
--- a/src/js/forms.js
+++ /dev/null
@@ -1,22 +0,0 @@
-$('form.form-register').submit(function(){
-    Botleagues.request({
-        endpoint: 'user',
-        method: 'POST',
-        data: {
-            email: $(this).find('input[name="email"]').val(),
-            password: $(this).find('input[name="password"]').val()
-        },
-        callback: BotleaguesCallback.register
-    });
-
-    event.preventDefault();
-});
-
-$('.btn-botleagues-login').focus(function(){
-    $('#login-block').slideDown();
-    $('#login-email').focus();
-});
-$('#login-form').submit(function(){
-    Botleagues.login($('#login-email').val(), $('#login-password').val());
-    event.preventDefault();
-});
\ No newline at end of file
diff --git a/src/js/main.coffee b/src/js/main.coffee
new file mode 100644
index 0000000..4bf9c20
--- /dev/null
+++ b/src/js/main.coffee
@@ -0,0 +1,29 @@
+$ -> 
+    # Show extra links if user is logged in
+    email = $.cookie(Botleagues.cookie_login_email)
+    setupLoginMenu() if email? && $.cookie(Botleagues.cookie_login_valid_till) > (new Date()).getTime()
+    return
+
+# Show extra links if user is logged in
+setupLoginMenu = ->
+    $('#nav .login-link').remove()
+
+    extra_links = 
+        'Leagues': '/leagues'
+        'My Bots': '/profile/bots'
+        'Profile': '/profile'
+        'Logout': '/logout'
+
+    for title, link of extra_links
+        li = $('<li>').append(
+                $('<a>')
+                    .attr 'role', 'presentation'
+                    .attr 'title', title
+                    .attr 'href', link
+                    .text title
+            )
+        if link == selected_page
+            li.addClass 'active'
+        li.appendTo $('#nav')
+
+    return
\ No newline at end of file
diff --git a/src/js/main.js b/src/js/main.js
deleted file mode 100644
index 5d17e02..0000000
--- a/src/js/main.js
+++ /dev/null
@@ -1,27 +0,0 @@
-$(document).ready(function(){
-
-    // Show profile link instead of login if user is logged in
-    var email = $.cookie(Botleagues.cookie_login_email);
-    if (typeof email != 'undefined' && $.cookie(Botleagues.cookie_login_valid_till) > (new Date()).getTime()) {
-        setupLoginMenu();
-    }
-});
-
-function setupLoginMenu() {
-    $('#nav .login-link').remove();
-
-    var extra_links = {'Leagues': '/leagues', 'My Bots': '/profile/bots', 'Profile': '/profile', 'Logout': '/logout'};
-
-    for (var text in extra_links) {
-        var li = $('<li>').append(
-            $('<a>')
-                .attr('role', 'presentation')
-                .attr('title', text)
-                .attr('href', extra_links[text])
-                .text(text));
-        if (extra_links[text] == selected_page) { // selected_page is added in layout-main.jade
-            li.addClass('active');
-        }
-        li.appendTo($('#nav'));
-    }
-}
\ No newline at end of file
diff --git a/src/js/profile.coffee b/src/js/profile.coffee
new file mode 100644
index 0000000..33d171b
--- /dev/null
+++ b/src/js/profile.coffee
@@ -0,0 +1,15 @@
+$ ->
+    # Show email address in page when logged in
+    setupGreeter()
+    return
+
+# Show email address in page when logged in
+setupGreeter = ->
+    $('.jumbotron .lead').append(' ' + $.cookie(Botleagues.cookie_login_email))
+    $('.header h3').append(
+        $('<span>')
+            .attr('id', 'banner-email')
+            .addClass('text-muted')
+            .text(' / ' + $.cookie(Botleagues.cookie_login_email))
+    )
+    return
\ No newline at end of file
diff --git a/src/js/profile.js b/src/js/profile.js
deleted file mode 100644
index f27e562..0000000
--- a/src/js/profile.js
+++ /dev/null
@@ -1,14 +0,0 @@
-$(document).ready(function(){
-    setupGreeter();
-});
-
-function setupGreeter() {
-    $('.jumbotron .lead').append(' ' + $.cookie(Botleagues.cookie_login_email));
-    
-    $('.header h3').append(
-        $('<span>')
-            .attr('id', 'banner-email')
-            .addClass('text-muted')
-            .text(' / ' + $.cookie(Botleagues.cookie_login_email))
-    );
-}
\ No newline at end of file
-- 
cgit v1.2.3


From 2388099227d1c0528e640ceb4631a35521201c76 Mon Sep 17 00:00:00 2001
From: Camil Staps
Date: Wed, 13 May 2015 23:10:22 +0200
Subject: Cleanup coffeescript

---
 src/js/forms.coffee   | 47 +++++++++++++++++++++++++++++------------------
 src/js/main.coffee    | 22 ++++++++++++----------
 src/js/profile.coffee | 16 +++++++++-------
 3 files changed, 50 insertions(+), 35 deletions(-)

diff --git a/src/js/forms.coffee b/src/js/forms.coffee
index e742160..71eb52b 100644
--- a/src/js/forms.coffee
+++ b/src/js/forms.coffee
@@ -1,25 +1,36 @@
 # Request API for registering
-$('form.form-register').submit ->
-    Botleagues.request
-        endpoint: 'user'
-        method: 'POST'
-        data:
-            email: $(this).find('input[name="email"]').val()
-            password: $(this).find('input[name="password"]').val()
-        callback: BotleaguesCallback.register
+$ 'form.form-register'
+    .submit ->
+        Botleagues.request
+            endpoint: 'user'
+            method: 'POST'
+            data:
+                email: 
+                    $ this
+                    .find 'input[name="email"]'
+                    .val()
+                password: 
+                    $ this
+                    .find 'input[name="password"]'
+                    .val()
+            callback: BotleaguesCallback.register
 
-    event.preventDefault()
+        event.preventDefault()
 
-    return
+        return
 
 # Show login form on click
-$('.btn-botleagues-login').focus ->
-    $('#login-block').slideDown()
-    $('#login-email').focus()
-    return
+$ '.btn-botleagues-login'
+    .focus ->
+        $ '#login-block'
+            .slideDown()
+        $ '#login-email'
+            .focus()
+        return
 
 # Request API for logging in
-$('#login-form').submit ->
-    Botleagues.login $('#login-email').val(), $('#login-password').val()
-    event.preventDefault()
-    return
\ No newline at end of file
+$ '#login-form'
+    .submit ->
+        Botleagues.login ($ '#login-email').val(), ($ '#login-password').val()
+        event.preventDefault()
+        return
\ No newline at end of file
diff --git a/src/js/main.coffee b/src/js/main.coffee
index 4bf9c20..5d21ede 100644
--- a/src/js/main.coffee
+++ b/src/js/main.coffee
@@ -1,12 +1,13 @@
 $ -> 
     # Show extra links if user is logged in
-    email = $.cookie(Botleagues.cookie_login_email)
+    email = $.cookie Botleagues.cookie_login_email
     setupLoginMenu() if email? && $.cookie(Botleagues.cookie_login_valid_till) > (new Date()).getTime()
     return
 
 # Show extra links if user is logged in
 setupLoginMenu = ->
-    $('#nav .login-link').remove()
+    $ '#nav .login-link'
+        .remove()
 
     extra_links = 
         'Leagues': '/leagues'
@@ -15,15 +16,16 @@ setupLoginMenu = ->
         'Logout': '/logout'
 
     for title, link of extra_links
-        li = $('<li>').append(
-                $('<a>')
-                    .attr 'role', 'presentation'
-                    .attr 'title', title
-                    .attr 'href', link
-                    .text title
-            )
+        li = $ '<li>'
+                .append(
+                    $ '<a>'
+                        .attr 'role', 'presentation'
+                        .attr 'title', title
+                        .attr 'href', link
+                        .text title
+                )
         if link == selected_page
             li.addClass 'active'
-        li.appendTo $('#nav')
+        li.appendTo ($ '#nav')
 
     return
\ No newline at end of file
diff --git a/src/js/profile.coffee b/src/js/profile.coffee
index 33d171b..7942088 100644
--- a/src/js/profile.coffee
+++ b/src/js/profile.coffee
@@ -5,11 +5,13 @@ $ ->
 
 # Show email address in page when logged in
 setupGreeter = ->
-    $('.jumbotron .lead').append(' ' + $.cookie(Botleagues.cookie_login_email))
-    $('.header h3').append(
-        $('<span>')
-            .attr('id', 'banner-email')
-            .addClass('text-muted')
-            .text(' / ' + $.cookie(Botleagues.cookie_login_email))
-    )
+    $ '.jumbotron .lead'
+        .append (' ' + $.cookie Botleagues.cookie_login_email)
+    $ '.header h3'
+        .append(
+            $ '<span>'
+                .attr 'id', 'banner-email'
+                .addClass 'text-muted'
+                .text(' / ' + $.cookie Botleagues.cookie_login_email)
+        )
     return
\ No newline at end of file
-- 
cgit v1.2.3


From 364b948040bcbfb9d6e210bbc235a37ab845ad45 Mon Sep 17 00:00:00 2001
From: Camil Staps
Date: Wed, 13 May 2015 23:15:06 +0200
Subject: Gulpfile: 3rd-party-styles; production task

---
 gulpfile.js | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/gulpfile.js b/gulpfile.js
index 4a0dff1..6817c03 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -38,6 +38,11 @@ gulp.task('rebuild', ['clean'], function() {
     gulp.start('all');
 });
 
+gulp.task('production', ['clean'], function(){
+    production = true;
+    gulp.start('all');
+});
+
 gulp.task('clean', function(cb) {
     del(['./build/assets/css', './build/assets/js', './build/assets/less', './build/assets/img', './build/assets/fonts', './build/*.html'], cb)
 });
@@ -108,9 +113,6 @@ gulp.task('3rd-party-styles', function() {
             // https://github.com/gulpjs/gulp/blob/master/docs/recipes/using-multiple-sources-in-one-task.md
             return merge(stream, gulp.src(['./build/assets/css/font-awesome.css', './build/assets/css/main.css']))
                 .pipe(concat('bootswatch.css'))
-                .pipe(gulp.dest(dst))
-                .pipe(rename({suffix: '.min'}))
-                .pipe(minifycss());
         })))
         .pipe(minifycss())
         .pipe(gulp.dest(dst));
-- 
cgit v1.2.3


From f7936e984be4341837c0d09723adeb379a07c54a Mon Sep 17 00:00:00 2001
From: Camil Staps
Date: Thu, 14 May 2015 10:46:08 +0200
Subject: small coffeescript fixes

---
 src/js/forms.coffee | 9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/src/js/forms.coffee b/src/js/forms.coffee
index 71eb52b..fe237c2 100644
--- a/src/js/forms.coffee
+++ b/src/js/forms.coffee
@@ -15,9 +15,7 @@ $ 'form.form-register'
                     .val()
             callback: BotleaguesCallback.register
 
-        event.preventDefault()
-
-        return
+        false
 
 # Show login form on click
 $ '.btn-botleagues-login'
@@ -26,11 +24,10 @@ $ '.btn-botleagues-login'
             .slideDown()
         $ '#login-email'
             .focus()
-        return
+        false
 
 # Request API for logging in
 $ '#login-form'
     .submit ->
         Botleagues.login ($ '#login-email').val(), ($ '#login-password').val()
-        event.preventDefault()
-        return
\ No newline at end of file
+        false
\ No newline at end of file
-- 
cgit v1.2.3


From 833546cb217f0be302a31fa2d5500b6a24815cbc Mon Sep 17 00:00:00 2001
From: Camil Staps
Date: Thu, 14 May 2015 11:42:36 +0200
Subject: Fixed bower version

---
 bower.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/bower.json b/bower.json
index ea0dd59..bb78112 100644
--- a/bower.json
+++ b/bower.json
@@ -15,7 +15,7 @@
   ],
   "dependencies": {
     "bootstrap": "~3.3.2",
-    "bootswatch": "~3.3.4+1",
+    "bootswatch": "~3.3.4",
     "fontawesome": "~4.3.0",
     "jquery-cookie": "~1.4.1"
   }
-- 
cgit v1.2.3


From 07bc5d3fc9490961c958710daf110bf49c4fe4fe Mon Sep 17 00:00:00 2001
From: Camil Staps
Date: Sun, 17 May 2015 00:41:44 +0200
Subject: Fixed gulpfile bug where // in a URL was turned into http://
 automatically by the clean-css minifier

---
 gulpfile.js | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/gulpfile.js b/gulpfile.js
index 6817c03..b22b542 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -92,7 +92,7 @@ gulp.task('3rd-party-styles', function() {
     return gulp.src(fileList)
         .pipe(changed(dst, {extension: '.css', destination: function(file){
             if (isBootswatchFile(file)) {
-                return 'bootswatch.css';
+                return bootswatch_dst;
             } else {
                 return file;
             }
@@ -111,10 +111,10 @@ gulp.task('3rd-party-styles', function() {
             
             // http://stackoverflow.com/questions/21719833/gulp-how-to-add-src-files-in-the-middle-of-a-pipe
             // https://github.com/gulpjs/gulp/blob/master/docs/recipes/using-multiple-sources-in-one-task.md
-            return merge(stream, gulp.src(['./build/assets/css/font-awesome.css', './build/assets/css/main.css']))
-                .pipe(concat('bootswatch.css'))
+            return merge(stream, gulp.src(['./build/assets/css/font-awesome.css']))
+                .pipe(concat(bootswatch_dst))
         })))
-        .pipe(minifycss())
+        .pipe(minifycss({processImport: false}))
         .pipe(gulp.dest(dst));
 });
 
-- 
cgit v1.2.3