diff --git a/.babelrc b/.babelrc
new file mode 100644
index 00000000..06dfb47f
--- /dev/null
+++ b/.babelrc
@@ -0,0 +1,20 @@
+{
+  "comments": false,
+  "presets": [
+    ["env", {
+      "targets": {
+        "browsers": [
+          "last 6 Chrome major versions",
+          "last 6 Firefox major versions",
+          "last 4 Safari major versions",
+          "last 4 Edge major versions",
+          "last 3 iOS major versions",
+          "last 3 Android major versions",
+          "last 2 ChromeAndroid major versions",
+          "Explorer 11"
+        ]
+      }
+    }],
+    "stage-2"
+  ]
+}
diff --git a/.eslintrc.json b/.eslintrc.json
index 283168f4..8bf80646 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -1,27 +1,14 @@
 {
-  "extends": "standard",
+  "extends": "requarks",
   "env": {
     "node": true,
     "es6": true,
     "jest": true
   },
   "globals": {
-    // Client
     "document": false,
     "navigator": false,
     "window": false,
-    "siteLang": false,
-    "socket": true,
-    "wikijs": true,
-    "FuseBox": false,
-    // Server
-    "appconfig": true,
-    "appdata": true,
-    "ROOTPATH": true,
-    "SERVERPATH": true,
-    "IS_DEBUG": true
-  },
-  "rules": {
-    "space-before-function-paren": 0
+    "FuseBox": false
   }
 }
diff --git a/.npmrc b/.npmrc
index 22b81d18..6d1bedf0 100644
--- a/.npmrc
+++ b/.npmrc
@@ -1 +1,2 @@
-save-prefix = "~"
+save-exact = true
+save-prefix = ""
diff --git a/.yarnrc b/.yarnrc
index 95888f66..d60dfee7 100644
--- a/.yarnrc
+++ b/.yarnrc
@@ -1 +1,2 @@
-save-prefix "~"
+save-exact true
+save-prefix ""
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 63458e51..1d7cde22 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -237,11 +237,6 @@ This project adheres to [Semantic Versioning](http://semver.org/).
 ### Changed
 - Updated dependencies + snyk policy
 
-[v1.0.11]: https://github.com/Requarks/wiki/releases/tag/v1.0.11
-[v1.0.10]: https://github.com/Requarks/wiki/releases/tag/v1.0.10
-[v1.0.9]: https://github.com/Requarks/wiki/releases/tag/v1.0.9
-[v1.0.8]: https://github.com/Requarks/wiki/releases/tag/v1.0.8
-[v1.0.7]: https://github.com/Requarks/wiki/releases/tag/v1.0.7
 [v1.0.6]: https://github.com/Requarks/wiki/releases/tag/v1.0.6
 [v1.0.5]: https://github.com/Requarks/wiki/releases/tag/v1.0.5
 [v1.0.4]: https://github.com/Requarks/wiki/releases/tag/v1.0.4
diff --git a/assets/images/bg.jpg b/assets/images/bg.jpg
new file mode 100644
index 00000000..d601fcfe
Binary files /dev/null and b/assets/images/bg.jpg differ
diff --git a/assets/images/bg_1.jpg b/assets/images/bg_1.jpg
deleted file mode 100644
index 1b85b7f0..00000000
Binary files a/assets/images/bg_1.jpg and /dev/null differ
diff --git a/assets/images/bg_2.jpg b/assets/images/bg_2.jpg
deleted file mode 100644
index df2c53be..00000000
Binary files a/assets/images/bg_2.jpg and /dev/null differ
diff --git a/assets/images/bg_3.jpg b/assets/images/bg_3.jpg
deleted file mode 100644
index 04be9fe7..00000000
Binary files a/assets/images/bg_3.jpg and /dev/null differ
diff --git a/assets/svg/auth-icon-azure.svg b/assets/svg/auth-icon-azure.svg
new file mode 100644
index 00000000..13f1c52e
--- /dev/null
+++ b/assets/svg/auth-icon-azure.svg
@@ -0,0 +1,8 @@
+<svg width="100%" height="100%" viewBox="0 0 159 158" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41421;">
+  <path fill="#51b5d7" d="M87.477,3.864c-4.583,-4.583 -12.024,-4.583 -16.608,0l-66.432,66.432c-4.583,4.583 -4.583,12.025 0,16.608l67.352,67.352c4.583,4.583 12.025,4.583 16.608,0l66.432,-66.432c4.583,-4.583 4.583,-12.025 0,-16.608l-67.352,-67.352Zm-14.477,44.282c-3.497,-2.176 -5.826,-6.054 -5.826,-10.472c0,-6.803 5.523,-12.326 12.326,-12.326c6.803,0 12.326,5.523 12.326,12.326c0,4.418 -2.329,8.296 -5.826,10.472l0,61.157c0.415,0.214 0.818,0.447 1.208,0.699l24.89,-24.89c-0.909,-1.718 -1.424,-3.676 -1.424,-5.753c0,-6.803 5.523,-12.326 12.326,-12.326c6.803,0 12.326,5.523 12.326,12.326c0,6.803 -5.523,12.326 -12.326,12.326c-1.493,0 -2.924,-0.266 -4.249,-0.753l-25.952,25.951c0.606,1.58 0.938,3.295 0.938,5.088c0,7.857 -6.38,14.236 -14.237,14.236c-7.857,0 -14.237,-6.379 -14.237,-14.236c0,-1.804 0.337,-3.531 0.95,-5.119l-26.466,-26.466c-1.182,0.377 -2.441,0.581 -3.747,0.581c-6.803,0 -12.326,-5.523 -12.326,-12.326c0,-6.803 5.523,-12.326 12.326,-12.326c6.803,0 12.326,5.523 12.326,12.326c0,2.254 -0.606,4.368 -1.665,6.187l25.157,25.157c0.382,-0.245 0.776,-0.473 1.182,-0.682l0,-61.157Z" />
+  <path fill="#97cbe1" d="M91.745,39.094l28.297,28.297c-4.527,1.116 -8.072,4.737 -9.079,9.306l-24.963,-24.963l0,-3.588c3.116,-1.939 5.306,-5.231 5.745,-9.052Zm-24.49,0c0.439,3.821 2.629,7.113 5.745,9.052l0,3.588l-24.846,24.846c-0.785,-4.655 -4.183,-8.427 -8.632,-9.753l27.733,-27.733Z" />
+  <circle fill="#97cbe1" cx="35.84" cy="78.701" r="6.701" />
+  <circle fill="#97cbe1" cx="123.16" cy="79.778" r="6.701" />
+  <circle fill="#97cbe1" cx="79.299" cy="37.243" r="6.701" />
+  <circle fill="#97cbe1" cx="79.633" cy="122.201" r="8.201" />
+</svg>
diff --git a/assets/svg/auth-icon-facebook.svg b/assets/svg/auth-icon-facebook.svg
new file mode 100644
index 00000000..fa706aa2
--- /dev/null
+++ b/assets/svg/auth-icon-facebook.svg
@@ -0,0 +1,3 @@
+<svg width="100%" height="100%" viewBox="0 0 500 500" preserveAspectRatio="xMinYMin meet">
+	<path fill="#3B5998" d="M288.714,500l0,-228.073l76.554,0l11.461,-88.885l-88.017,0l0,-56.749c0,-25.735 7.145,-43.271 44.049,-43.271l47.067,-0.022l0,-79.498c-8.141,-1.081 -36.082,-3.502 -68.584,-3.502c-67.862,0 -114.321,41.422 -114.321,117.492l0,65.55l-76.751,0l0,88.885l76.751,0l0,228.071l91.791,0l0,0.002Z" style="fill-rule:nonzero;"/>
+</svg>
\ No newline at end of file
diff --git a/assets/svg/auth-icon-github.svg b/assets/svg/auth-icon-github.svg
new file mode 100644
index 00000000..18e9450e
--- /dev/null
+++ b/assets/svg/auth-icon-github.svg
@@ -0,0 +1 @@
+<svg width="2500" height="2432" viewBox="0 0 256 249" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMinYMin meet"><g fill="#161614"><path d="M127.505 0C57.095 0 0 57.085 0 127.505c0 56.336 36.534 104.13 87.196 120.99 6.372 1.18 8.712-2.766 8.712-6.134 0-3.04-.119-13.085-.173-23.739-35.473 7.713-42.958-15.044-42.958-15.044-5.8-14.738-14.157-18.656-14.157-18.656-11.568-7.914.872-7.752.872-7.752 12.804.9 19.546 13.14 19.546 13.14 11.372 19.493 29.828 13.857 37.104 10.6 1.144-8.242 4.449-13.866 8.095-17.05-28.32-3.225-58.092-14.158-58.092-63.014 0-13.92 4.981-25.295 13.138-34.224-1.324-3.212-5.688-16.18 1.235-33.743 0 0 10.707-3.427 35.073 13.07 10.17-2.826 21.078-4.242 31.914-4.29 10.836.048 21.752 1.464 31.942 4.29 24.337-16.497 35.029-13.07 35.029-13.07 6.94 17.563 2.574 30.531 1.25 33.743 8.175 8.929 13.122 20.303 13.122 34.224 0 48.972-29.828 59.756-58.22 62.912 4.573 3.957 8.648 11.717 8.648 23.612 0 17.06-.148 30.791-.148 34.991 0 3.393 2.295 7.369 8.759 6.117 50.634-16.879 87.122-64.656 87.122-120.973C255.009 57.085 197.922 0 127.505 0"/><path d="M47.755 181.634c-.28.633-1.278.823-2.185.389-.925-.416-1.445-1.28-1.145-1.916.275-.652 1.273-.834 2.196-.396.927.415 1.455 1.287 1.134 1.923M54.027 187.23c-.608.564-1.797.302-2.604-.589-.834-.889-.99-2.077-.373-2.65.627-.563 1.78-.3 2.616.59.834.899.996 2.08.36 2.65M58.33 194.39c-.782.543-2.06.034-2.849-1.1-.781-1.133-.781-2.493.017-3.038.792-.545 2.05-.055 2.85 1.07.78 1.153.78 2.513-.019 3.069M65.606 202.683c-.699.77-2.187.564-3.277-.488-1.114-1.028-1.425-2.487-.724-3.258.707-.772 2.204-.555 3.302.488 1.107 1.026 1.445 2.496.7 3.258M75.01 205.483c-.307.998-1.741 1.452-3.185 1.028-1.442-.437-2.386-1.607-2.095-2.616.3-1.005 1.74-1.478 3.195-1.024 1.44.435 2.386 1.596 2.086 2.612M85.714 206.67c.036 1.052-1.189 1.924-2.705 1.943-1.525.033-2.758-.818-2.774-1.852 0-1.062 1.197-1.926 2.721-1.951 1.516-.03 2.758.815 2.758 1.86M96.228 206.267c.182 1.026-.872 2.08-2.377 2.36-1.48.27-2.85-.363-3.039-1.38-.184-1.052.89-2.105 2.367-2.378 1.508-.262 2.857.355 3.049 1.398"/></g></svg>
\ No newline at end of file
diff --git a/assets/svg/auth-icon-google.svg b/assets/svg/auth-icon-google.svg
new file mode 100644
index 00000000..06dc52f0
--- /dev/null
+++ b/assets/svg/auth-icon-google.svg
@@ -0,0 +1 @@
+<svg width="2443" height="2500" viewBox="0 0 256 262" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid"><path d="M255.878 133.451c0-10.734-.871-18.567-2.756-26.69H130.55v48.448h71.947c-1.45 12.04-9.283 30.172-26.69 42.356l-.244 1.622 38.755 30.023 2.685.268c24.659-22.774 38.875-56.282 38.875-96.027" fill="#4285F4"/><path d="M130.55 261.1c35.248 0 64.839-11.605 86.453-31.622l-41.196-31.913c-11.024 7.688-25.82 13.055-45.257 13.055-34.523 0-63.824-22.773-74.269-54.25l-1.531.13-40.298 31.187-.527 1.465C35.393 231.798 79.49 261.1 130.55 261.1" fill="#34A853"/><path d="M56.281 156.37c-2.756-8.123-4.351-16.827-4.351-25.82 0-8.994 1.595-17.697 4.206-25.82l-.073-1.73L15.26 71.312l-1.335.635C5.077 89.644 0 109.517 0 130.55s5.077 40.905 13.925 58.602l42.356-32.782" fill="#FBBC05"/><path d="M130.55 50.479c24.514 0 41.05 10.589 50.479 19.438l36.844-35.974C195.245 12.91 165.798 0 130.55 0 79.49 0 35.393 29.301 13.925 71.947l42.211 32.783c10.59-31.477 39.891-54.251 74.414-54.251" fill="#EB4335"/></svg>
\ No newline at end of file
diff --git a/assets/svg/auth-icon-ldap.svg b/assets/svg/auth-icon-ldap.svg
new file mode 100644
index 00000000..679fc237
--- /dev/null
+++ b/assets/svg/auth-icon-ldap.svg
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 19.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 width="48px" height="48px" viewBox="0 0 48 48" enable-background="new 0 0 48 48" xml:space="preserve">
+<path fill="#458BC4" d="M44.804,30.404l-20-27C24.615,3.15,24.308,3.023,24,3.023V46c0.2,0,0.401-0.061,0.573-0.181l20-14
+	c0.222-0.155,0.37-0.393,0.414-0.659C45.03,30.895,44.964,30.622,44.804,30.404z"/>
+<path fill="#43A6DD" d="M23.196,3.405l-20,27c-0.16,0.218-0.227,0.49-0.184,0.756c0.044,0.267,0.192,0.504,0.414,0.659l20,14
+	C23.599,45.939,23.8,46,24,46V3.023C23.692,3.023,23.385,3.15,23.196,3.405z"/>
+</svg>
diff --git a/assets/svg/auth-icon-local.svg b/assets/svg/auth-icon-local.svg
new file mode 100644
index 00000000..da2fe997
--- /dev/null
+++ b/assets/svg/auth-icon-local.svg
@@ -0,0 +1,8 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 width="64px" height="64px" viewBox="0 0 64 64" enable-background="new 0 0 64 64" xml:space="preserve">
+<path d="M32,19c13.089,0,27-3.154,27-9S45.089,1,32,1S5,4.154,5,10S18.911,19,32,19z"/>
+<path d="M32,41c13.089,0,27-3.154,27-9V14.436c-1.481,1.493-3.963,2.968-8.022,4.174C45.864,20.128,38.946,21,32,21
+	s-13.864-0.872-18.978-2.391C8.963,17.403,6.481,15.929,5,14.436V32C5,37.846,18.911,41,32,41z"/>
+<path d="M32,63c13.089,0,27-3.154,27-9V36.436c-1.481,1.493-3.963,2.968-8.022,4.174C45.864,42.128,38.946,43,32,43
+	s-13.864-0.872-18.978-2.391C8.963,39.403,6.481,37.929,5,36.436V54C5,59.846,18.911,63,32,63z"/>
+</svg>
diff --git a/assets/svg/auth-icon-microsoft.svg b/assets/svg/auth-icon-microsoft.svg
new file mode 100644
index 00000000..0d47e89a
--- /dev/null
+++ b/assets/svg/auth-icon-microsoft.svg
@@ -0,0 +1 @@
+<svg width="2490" height="2500" viewBox="0 0 256 257" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid"><path d="M0 36.357L104.62 22.11l.045 100.914-104.57.595L0 36.358zm104.57 98.293l.08 101.002L.081 221.275l-.006-87.302 104.494.677zm12.682-114.405L255.968 0v121.74l-138.716 1.1V20.246zM256 135.6l-.033 121.191-138.716-19.578-.194-101.84L256 135.6z" fill="#00ADEF"/></svg>
\ No newline at end of file
diff --git a/assets/svg/auth-icon-slack.svg b/assets/svg/auth-icon-slack.svg
new file mode 100644
index 00000000..47232d6d
--- /dev/null
+++ b/assets/svg/auth-icon-slack.svg
@@ -0,0 +1 @@
+<svg width="2500" height="2500" viewBox="0 0 256 256" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid"><path d="M165.964 15.838c-3.89-11.975-16.752-18.528-28.725-14.636-11.975 3.89-18.528 16.752-14.636 28.725l58.947 181.365c4.048 11.187 16.132 17.473 27.732 14.135 12.1-3.483 19.475-16.334 15.614-28.217L165.964 15.838" fill="#DFA22F"/><path d="M74.626 45.516C70.734 33.542 57.873 26.989 45.9 30.879 33.924 34.77 27.37 47.631 31.263 59.606l58.948 181.366c4.047 11.186 16.132 17.473 27.732 14.132 12.099-3.481 19.474-16.332 15.613-28.217L74.626 45.516" fill="#3CB187"/><path d="M240.162 166.045c11.975-3.89 18.526-16.75 14.636-28.726-3.89-11.973-16.752-18.527-28.725-14.636L44.708 181.632c-11.187 4.046-17.473 16.13-14.135 27.73 3.483 12.099 16.334 19.475 28.217 15.614l181.372-58.93" fill="#CE1E5B"/><path d="M82.508 217.27l43.347-14.084-14.086-43.352-43.35 14.09 14.089 43.347" fill="#392538"/><path d="M173.847 187.591c16.388-5.323 31.62-10.273 43.348-14.084l-14.088-43.36-43.35 14.09 14.09 43.354" fill="#BB242A"/><path d="M210.484 74.706c11.974-3.89 18.527-16.751 14.637-28.727-3.89-11.973-16.752-18.526-28.727-14.636L15.028 90.293C3.842 94.337-2.445 106.422.896 118.022c3.481 12.098 16.332 19.474 28.217 15.613l181.371-58.93" fill="#72C5CD"/><path d="M52.822 125.933c11.805-3.836 27.025-8.782 43.354-14.086-5.323-16.39-10.273-31.622-14.084-43.352l-43.36 14.092 14.09 43.346" fill="#248C73"/><path d="M144.16 96.256l43.356-14.088a546179.21 546179.21 0 0 0-14.089-43.36L130.07 52.9l14.09 43.356" fill="#62803A"/></svg>
\ No newline at end of file
diff --git a/assets/svg/login-bg-dark.svg b/assets/svg/login-bg-dark.svg
new file mode 100644
index 00000000..8ab32dde
--- /dev/null
+++ b/assets/svg/login-bg-dark.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg width="100%" height="100%" viewBox="0 0 1500 1000" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41421;">
+    <path d="M1500,543c0,0 -135.753,54.677 -252.197,101.577c-106.023,42.702 -223.596,47.2 -332.571,12.724c-56.088,-17.745 -118.404,-37.46 -173.999,-55.048c-103.773,-32.831 -216.376,-22.709 -312.631,28.103c0,0 0,0.001 0,0.001c-94.821,50.055 -206.441,57.476 -307.053,20.415c-63.317,-23.322 -121.549,-44.772 -121.549,-44.772l0,417l1500,0l0,-480Z" style="fill:#2d2d2d;fill-opacity:0.282609;"/>
+    <path d="M1510,580c0,0 -144.155,47.882 -252.311,83.806c-74.651,24.796 -156.199,17.958 -225.679,-18.923c0,0 0,0 0,0c-62.207,-33.021 -133.629,-44.415 -203.023,-32.389c-98.381,17.051 -244.859,42.438 -352.664,61.121c-92.259,15.99 -187.076,8.079 -275.41,-22.977c-93.342,-32.818 -200.913,-70.638 -200.913,-70.638l0,466l1500,0l10,-466Z" style="fill:#2d2d2d;fill-opacity:0.550725;"/>
+    <path d="M1500,650c0,0 -143.367,28.581 -239.425,47.731c-56.087,11.181 -113.694,12.508 -170.237,3.922c-74.75,-11.351 -183.318,-27.838 -261.719,-39.743c-65.252,-9.909 -131.707,-8.759 -196.577,3.4c-49.655,9.308 -109.704,20.564 -158.992,29.803c-63.125,11.833 -127.839,12.479 -191.188,1.911c-111.875,-18.665 -281.862,-47.024 -281.862,-47.024l0,430l1500,0l0,-430Z" style="fill:#2d2d2d;"/>
+</svg>
diff --git a/assets/svg/login-bg.svg b/assets/svg/login-bg.svg
new file mode 100644
index 00000000..bb1c6ffb
--- /dev/null
+++ b/assets/svg/login-bg.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg width="100%" height="100%" viewBox="0 0 1500 1000" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41421;">
+    <path d="M1500,543c0,0 -135.753,54.677 -252.197,101.577c-106.023,42.702 -223.596,47.2 -332.571,12.724c-56.088,-17.745 -118.404,-37.46 -173.999,-55.048c-103.773,-32.831 -216.376,-22.709 -312.631,28.103c0,0 0,0.001 0,0.001c-94.821,50.055 -206.441,57.476 -307.053,20.415c-63.317,-23.322 -121.549,-44.772 -121.549,-44.772l0,417l1500,0l0,-480Z" style="fill:#fff;fill-opacity:0.282609;"/>
+    <path d="M1510,580c0,0 -144.155,47.882 -252.311,83.806c-74.651,24.796 -156.199,17.958 -225.679,-18.923c0,0 0,0 0,0c-62.207,-33.021 -133.629,-44.415 -203.023,-32.389c-98.381,17.051 -244.859,42.438 -352.664,61.121c-92.259,15.99 -187.076,8.079 -275.41,-22.977c-93.342,-32.818 -200.913,-70.638 -200.913,-70.638l0,466l1500,0l10,-466Z" style="fill:#fff;fill-opacity:0.550725;"/>
+    <path d="M1500,650c0,0 -143.367,28.581 -239.425,47.731c-56.087,11.181 -113.694,12.508 -170.237,3.922c-74.75,-11.351 -183.318,-27.838 -261.719,-39.743c-65.252,-9.909 -131.707,-8.759 -196.577,3.4c-49.655,9.308 -109.704,20.564 -158.992,29.803c-63.125,11.833 -127.839,12.479 -191.188,1.911c-111.875,-18.665 -281.862,-47.024 -281.862,-47.024l0,430l1500,0l0,-430Z" style="fill:#fff;"/>
+</svg>
diff --git a/client/configure.js b/client/configure.js
deleted file mode 100644
index 714ff901..00000000
--- a/client/configure.js
+++ /dev/null
@@ -1,4 +0,0 @@
-'use strict'
-
-require('./scss/configure.scss')
-require('./js/configure.js')
diff --git a/client/index.js b/client/index.js
index 48f04872..7f5c2c19 100644
--- a/client/index.js
+++ b/client/index.js
@@ -1,17 +1,4 @@
 'use strict'
 
-let logic = document.documentElement.dataset.logic
-
-switch (logic) {
-  case 'error':
-    require('./scss/error.scss')
-    break
-  case 'login':
-    require('./scss/login.scss')
-    require('./js/login.js')
-    break
-  default:
-    require('./scss/app.scss')
-    require('./js/app.js')
-    break
-}
+require('./scss/app.scss')
+require('./js/app.js')
diff --git a/client/js/app.js b/client/js/app.js
index 9a9c3b1b..67601a6f 100644
--- a/client/js/app.js
+++ b/client/js/app.js
@@ -1,28 +1,28 @@
 'use strict'
 
-/* global $, siteRoot */
+/* global siteConfig */
 /* eslint-disable no-new */
 
+import CONSTANTS from './constants'
+
 import Vue from 'vue'
 import VueResource from 'vue-resource'
 import VueClipboards from 'vue-clipboards'
-import VueLodash from 'vue-lodash'
+import VeeValidate from 'vee-validate'
+import { ApolloClient, createBatchingNetworkInterface } from 'apollo-client'
 import store from './store'
-import io from 'socket-io-client'
-import i18next from 'i18next'
-import i18nextXHR from 'i18next-xhr-backend'
-import VueI18Next from '@panter/vue-i18next'
-import 'jquery-contextmenu'
-import 'jquery-simple-upload'
-import 'jquery-smooth-scroll'
-import 'jquery-sticky'
+
+// ====================================
+// Load Modules
+// ====================================
+
+import localization from './modules/localization'
 
 // ====================================
 // Load Helpers
 // ====================================
 
 import helpers from './helpers'
-import _ from './helpers/lodash'
 
 // ====================================
 // Load Vue Components
@@ -36,6 +36,7 @@ import editorFileComponent from './components/editor-file.vue'
 import editorVideoComponent from './components/editor-video.vue'
 import historyComponent from './components/history.vue'
 import loadingSpinnerComponent from './components/loading-spinner.vue'
+import loginComponent from './components/login.vue'
 import modalCreatePageComponent from './components/modal-create-page.vue'
 import modalCreateUserComponent from './components/modal-create-user.vue'
 import modalDeletePageComponent from './components/modal-delete-page.vue'
@@ -53,19 +54,48 @@ import adminEditUserComponent from './pages/admin-edit-user.component.js'
 import adminProfileComponent from './pages/admin-profile.component.js'
 import adminSettingsComponent from './pages/admin-settings.component.js'
 import adminThemeComponent from './pages/admin-theme.component.js'
+import configManagerComponent from './components/config-manager.component.js'
 import contentViewComponent from './pages/content-view.component.js'
 import editorComponent from './components/editor.component.js'
 import sourceViewComponent from './pages/source-view.component.js'
 
+// ====================================
+// Initialize Global Vars
+// ====================================
+
+window.wiki = null
+window.CONSTANTS = CONSTANTS
+
+// ====================================
+// Initialize Apollo Client (GraphQL)
+// ====================================
+
+window.graphQL = new ApolloClient({
+  networkInterface: createBatchingNetworkInterface({
+    uri: window.location.protocol + '//' + window.location.host + siteConfig.path + '/graphql'
+  }),
+  connectToDevTools: true
+})
+
 // ====================================
 // Initialize Vue Modules
 // ====================================
 
 Vue.use(VueResource)
 Vue.use(VueClipboards)
-Vue.use(VueI18Next)
-Vue.use(VueLodash, _)
+Vue.use(localization.VueI18Next)
 Vue.use(helpers)
+Vue.use(VeeValidate, {
+  enableAutoClasses: true,
+  classNames: {
+    touched: 'is-touched', // the control has been blurred
+    untouched: 'is-untouched', // the control hasn't been blurred
+    valid: 'is-valid', // model is valid
+    invalid: 'is-invalid', // model is invalid
+    pristine: 'is-pristine', // control has not been interacted with
+    dirty: 'is-dirty' // control has been interacted with
+  }
+})
 
 // ====================================
 // Register Vue Components
@@ -78,6 +108,7 @@ Vue.component('adminSettings', adminSettingsComponent)
 Vue.component('adminTheme', adminThemeComponent)
 Vue.component('anchor', anchorComponent)
 Vue.component('colorPicker', colorPickerComponent)
+Vue.component('configManager', configManagerComponent)
 Vue.component('contentView', contentViewComponent)
 Vue.component('editor', editorComponent)
 Vue.component('editorCodeblock', editorCodeblockComponent)
@@ -85,6 +116,7 @@ Vue.component('editorFile', editorFileComponent)
 Vue.component('editorVideo', editorVideoComponent)
 Vue.component('history', historyComponent)
 Vue.component('loadingSpinner', loadingSpinnerComponent)
+Vue.component('login', loginComponent)
 Vue.component('modalCreatePage', modalCreatePageComponent)
 Vue.component('modalCreateUser', modalCreateUserComponent)
 Vue.component('modalDeletePage', modalDeletePageComponent)
@@ -99,52 +131,26 @@ Vue.component('sourceView', sourceViewComponent)
 Vue.component('toggle', toggleComponent)
 Vue.component('tree', treeComponent)
 
-// ====================================
-// Load Localization strings
-// ====================================
-
-i18next
-  .use(i18nextXHR)
-  .init({
-    backend: {
-      loadPath: siteRoot + '/js/i18n/{{lng}}.json'
-    },
-    lng: siteLang,
-    fallbackLng: siteLang
-  })
-
-$(() => {
+document.addEventListener('DOMContentLoaded', ev => {
   // ====================================
   // Notifications
   // ====================================
 
-  $(window).bind('beforeunload', () => {
+  window.addEventListener('beforeunload', () => {
     store.dispatch('startLoading')
   })
-  $(document).ajaxSend(() => {
-    store.dispatch('startLoading')
-  }).ajaxComplete(() => {
-    store.dispatch('stopLoading')
-  })
-
-  // ====================================
-  // Establish WebSocket connection
-  // ====================================
-
-  let socket = io(window.location.origin)
-  window.socket = socket
 
   // ====================================
   // Bootstrap Vue
   // ====================================
 
-  const i18n = new VueI18Next(i18next)
-  window.wikijs = new Vue({
+  const i18n = localization.init()
+  window.wiki = new Vue({
     mixins: [helpers],
     components: {},
     store,
     i18n,
-    el: '#root',
+    el: '#app',
     methods: {
       changeTheme(opts) {
         this.$el.className = `has-stickynav is-primary-${opts.primary} is-alternate-${opts.alt}`
@@ -153,9 +159,7 @@ $(() => {
       }
     },
     mounted() {
-      $('a:not(.toc-anchor)').smoothScroll({ speed: 500, offset: -50 })
-      $('#header').sticky({ topSpacing: 0 })
-      $('.sidebar-pagecontents').sticky({ topSpacing: 15, bottomSpacing: 75 })
+
     }
   })
 })
diff --git a/client/js/app.old.js b/client/js/app.old.js
new file mode 100644
index 00000000..fc69cfc3
--- /dev/null
+++ b/client/js/app.old.js
@@ -0,0 +1,153 @@
+'use strict'
+
+/* global $, siteConfig */
+/* eslint-disable no-new */
+
+import Vue from 'vue'
+import VueResource from 'vue-resource'
+import VueClipboards from 'vue-clipboards'
+import VueLodash from 'vue-lodash'
+import store from './store'
+import i18next from 'i18next'
+import i18nextXHR from 'i18next-xhr-backend'
+import VueI18Next from '@panter/vue-i18next'
+import 'jquery-contextmenu'
+import 'jquery-simple-upload'
+import 'jquery-smooth-scroll'
+import 'jquery-sticky'
+
+// ====================================
+// Load Helpers
+// ====================================
+
+import helpers from './helpers'
+import _ from './helpers/lodash'
+
+// ====================================
+// Load Vue Components
+// ====================================
+
+import alertComponent from './components/alert.vue'
+import anchorComponent from './components/anchor.vue'
+import colorPickerComponent from './components/color-picker.vue'
+import editorCodeblockComponent from './components/editor-codeblock.vue'
+import editorFileComponent from './components/editor-file.vue'
+import editorVideoComponent from './components/editor-video.vue'
+import historyComponent from './components/history.vue'
+import loadingSpinnerComponent from './components/loading-spinner.vue'
+import modalCreatePageComponent from './components/modal-create-page.vue'
+import modalCreateUserComponent from './components/modal-create-user.vue'
+import modalDeleteUserComponent from './components/modal-delete-user.vue'
+import modalDiscardPageComponent from './components/modal-discard-page.vue'
+import modalMovePageComponent from './components/modal-move-page.vue'
+import modalProfile2faComponent from './components/modal-profile-2fa.vue'
+import modalUpgradeSystemComponent from './components/modal-upgrade-system.vue'
+import pageLoaderComponent from './components/page-loader.vue'
+import searchComponent from './components/search.vue'
+import toggleComponent from './components/toggle.vue'
+import treeComponent from './components/tree.vue'
+
+import adminEditUserComponent from './pages/admin-edit-user.component.js'
+import adminProfileComponent from './pages/admin-profile.component.js'
+import adminSettingsComponent from './pages/admin-settings.component.js'
+import adminThemeComponent from './pages/admin-theme.component.js'
+import contentViewComponent from './pages/content-view.component.js'
+import editorComponent from './components/editor.component.js'
+import sourceViewComponent from './pages/source-view.component.js'
+
+// ====================================
+// Initialize Vue Modules
+// ====================================
+
+Vue.use(VueResource)
+Vue.use(VueClipboards)
+Vue.use(VueI18Next)
+Vue.use(VueLodash, _)
+Vue.use(helpers)
+
+// ====================================
+// Register Vue Components
+// ====================================
+
+Vue.component('alert', alertComponent)
+Vue.component('adminEditUser', adminEditUserComponent)
+Vue.component('adminProfile', adminProfileComponent)
+Vue.component('adminSettings', adminSettingsComponent)
+Vue.component('adminTheme', adminThemeComponent)
+Vue.component('anchor', anchorComponent)
+Vue.component('colorPicker', colorPickerComponent)
+Vue.component('contentView', contentViewComponent)
+Vue.component('editor', editorComponent)
+Vue.component('editorCodeblock', editorCodeblockComponent)
+Vue.component('editorFile', editorFileComponent)
+Vue.component('editorVideo', editorVideoComponent)
+Vue.component('history', historyComponent)
+Vue.component('loadingSpinner', loadingSpinnerComponent)
+Vue.component('modalCreatePage', modalCreatePageComponent)
+Vue.component('modalCreateUser', modalCreateUserComponent)
+Vue.component('modalDeleteUser', modalDeleteUserComponent)
+Vue.component('modalDiscardPage', modalDiscardPageComponent)
+Vue.component('modalMovePage', modalMovePageComponent)
+Vue.component('modalProfile2fa', modalProfile2faComponent)
+Vue.component('modalUpgradeSystem', modalUpgradeSystemComponent)
+Vue.component('pageLoader', pageLoaderComponent)
+Vue.component('search', searchComponent)
+Vue.component('sourceView', sourceViewComponent)
+Vue.component('toggle', toggleComponent)
+Vue.component('tree', treeComponent)
+
+// ====================================
+// Load Localization strings
+// ====================================
+
+i18next
+  .use(i18nextXHR)
+  .init({
+    backend: {
+      loadPath: siteConfig.path + '/js/i18n/{{lng}}.json'
+    },
+    lng: siteConfig.lang,
+    fallbackLng: siteConfig.lang
+  })
+
+$(() => {
+  // ====================================
+  // Notifications
+  // ====================================
+
+  $(window).bind('beforeunload', () => {
+    store.dispatch('startLoading')
+  })
+  $(document).ajaxSend(() => {
+    store.dispatch('startLoading')
+  }).ajaxComplete(() => {
+    store.dispatch('stopLoading')
+  })
+
+  // ====================================
+  // Bootstrap Vue
+  // ====================================
+
+  const i18n = new VueI18Next(i18next)
+  if (document.querySelector('#root')) {
+    window.wikijs = new Vue({
+      mixins: [helpers],
+      components: {},
+      store,
+      i18n,
+      el: '#root',
+      methods: {
+        changeTheme(opts) {
+          this.$el.className = `has-stickynav is-primary-${opts.primary} is-alternate-${opts.alt}`
+          this.$refs.header.className = `nav is-${opts.primary}`
+          this.$refs.footer.className = `footer is-${opts.footer}`
+        }
+      },
+      mounted() {
+        $('a:not(.toc-anchor)').smoothScroll({ speed: 500, offset: -50 })
+        $('#header').sticky({ topSpacing: 0 })
+        $('.sidebar-pagecontents').sticky({ topSpacing: 15, bottomSpacing: 75 })
+      }
+    })
+  }
+})
diff --git a/client/js/components/config-manager.component.js b/client/js/components/config-manager.component.js
new file mode 100644
index 00000000..a6cea82c
--- /dev/null
+++ b/client/js/components/config-manager.component.js
@@ -0,0 +1,239 @@
+/* global siteConfig */
+
+import axios from 'axios'
+
+export default {
+  name: 'configManager',
+  data() {
+    return {
+      loading: false,
+      state: 'welcome',
+      syscheck: {
+        ok: false,
+        error: '',
+        results: []
+      },
+      dbcheck: {
+        ok: false,
+        error: ''
+      },
+      gitcheck: {
+        ok: false,
+        error: ''
+      },
+      final: {
+        ok: false,
+        error: '',
+        results: []
+      },
+      conf: {
+        telemetry: true,
+        upgrade: false,
+        title: siteConfig.title || 'Wiki',
+        host: siteConfig.host || 'http://',
+        port: siteConfig.port || 80,
+        lang: siteConfig.lang || 'en',
+        public: (siteConfig.public === true),
+        pathData: './data',
+        pathRepo: './repo',
+        gitUseRemote: (siteConfig.git !== false),
+        gitUrl: '',
+        gitBranch: 'master',
+        gitAuthType: 'ssh',
+        gitAuthSSHKey: '',
+        gitAuthUser: '',
+        gitAuthPass: '',
+        gitAuthSSL: true,
+        gitShowUserEmail: true,
+        gitServerEmail: '',
+        adminEmail: '',
+        adminPassword: '',
+        adminPasswordConfirm: ''
+      },
+      considerations: {
+        https: false,
+        port: false,
+        localhost: false
+      }
+    }
+  },
+  computed: {
+    currentProgress: function () {
+      let perc = '0%'
+      switch (this.state) {
+        case 'welcome':
+          perc = '0%'
+          break
+        case 'syscheck':
+          perc = (this.syscheck.ok) ? '15%' : '5%'
+          break
+        case 'general':
+          perc = '25%'
+          break
+        case 'considerations':
+          perc = '30%'
+          break
+        case 'git':
+          perc = '50%'
+          break
+        case 'gitcheck':
+          perc = (this.gitcheck.ok) ? '70%' : '55%'
+          break
+        case 'admin':
+          perc = '75%'
+          break
+      }
+      return perc
+    }
+  },
+  mounted: function () {
+    /* if (appconfig.paths) {
+      this.conf.pathData = appconfig.paths.data || './data'
+      this.conf.pathRepo = appconfig.paths.repo || './repo'
+    }
+    if (appconfig.git !== false && _.isPlainObject(appconfig.git)) {
+      this.conf.gitUrl = appconfig.git.url || ''
+      this.conf.gitBranch = appconfig.git.branch || 'master'
+      this.conf.gitShowUserEmail = (appconfig.git.showUserEmail !== false)
+      this.conf.gitServerEmail = appconfig.git.serverEmail || ''
+      if (_.isPlainObject(appconfig.git.auth)) {
+        this.conf.gitAuthType = appconfig.git.auth.type || 'ssh'
+        this.conf.gitAuthSSHKey = appconfig.git.auth.privateKey || ''
+        this.conf.gitAuthUser = appconfig.git.auth.username || ''
+        this.conf.gitAuthPass = appconfig.git.auth.password || ''
+        this.conf.gitAuthSSL = (appconfig.git.auth.sslVerify !== false)
+      }
+    } */
+  },
+  methods: {
+    proceedToWelcome: function (ev) {
+      this.state = 'welcome'
+      this.loading = false
+    },
+    proceedToSyscheck: function (ev) {
+      let self = this
+      this.state = 'syscheck'
+      this.loading = true
+      self.syscheck = {
+        ok: false,
+        error: '',
+        results: []
+      }
+
+      this.$helpers._.delay(() => {
+        axios.post('/syscheck').then(resp => {
+          if (resp.data.ok === true) {
+            self.syscheck.ok = true
+            self.syscheck.results = resp.data.results
+          } else {
+            self.syscheck.ok = false
+            self.syscheck.error = resp.data.error
+          }
+          self.loading = false
+          self.$nextTick()
+        }).catch(err => {
+          window.alert(err.message)
+        })
+      }, 1000)
+    },
+    proceedToGeneral: function (ev) {
+      let self = this
+      self.state = 'general'
+      self.loading = false
+      self.$nextTick(() => {
+        self.$validator.validateAll('general')
+      })
+    },
+    proceedToConsiderations: function (ev) {
+      this.considerations = {
+        https: !this.$helpers._.startsWith(this.conf.host, 'https'),
+        port: false, // TODO
+        localhost: this.$helpers._.includes(this.conf.host, 'localhost')
+      }
+      this.state = 'considerations'
+      this.loading = false
+    },
+    proceedToGit: function (ev) {
+      let self = this
+      self.state = 'git'
+      self.loading = false
+      self.$nextTick(() => {
+        self.$validator.validateAll('git')
+      })
+    },
+    proceedToGitCheck: function (ev) {
+      let self = this
+      this.state = 'gitcheck'
+      this.loading = true
+      self.gitcheck = {
+        ok: false,
+        results: [],
+        error: ''
+      }
+
+      this.$helpers._.delay(() => {
+        axios.post('/gitcheck', self.conf).then(resp => {
+          if (resp.data.ok === true) {
+            self.gitcheck.ok = true
+            self.gitcheck.results = resp.data.results
+          } else {
+            self.gitcheck.ok = false
+            self.gitcheck.error = resp.data.error
+          }
+          self.loading = false
+          self.$nextTick()
+        }).catch(err => {
+          window.alert(err.message)
+        })
+      }, 1000)
+    },
+    proceedToAdmin: function (ev) {
+      let self = this
+      self.state = 'admin'
+      self.loading = false
+      self.$nextTick(() => {
+        self.$validator.validateAll('admin')
+      })
+    },
+    proceedToFinal: function (ev) {
+      let self = this
+      self.state = 'final'
+      self.loading = true
+      self.final = {
+        ok: false,
+        error: '',
+        results: []
+      }
+
+      this.$helpers._.delay(() => {
+        axios.post('/finalize', self.conf).then(resp => {
+          if (resp.data.ok === true) {
+            self.final.ok = true
+            self.final.results = resp.data.results
+          } else {
+            self.final.ok = false
+            self.final.error = resp.data.error
+          }
+          self.loading = false
+          self.$nextTick()
+        }).catch(err => {
+          window.alert(err.message)
+        })
+      }, 1000)
+    },
+    finish: function (ev) {
+      let self = this
+      self.state = 'restart'
+
+      this.$helpers._.delay(() => {
+        axios.post('/restart', {}).then(resp => {
+          this.$helpers._.delay(() => {
+            window.location.assign(self.conf.host)
+          }, 30000)
+        }).catch(err => {
+          window.alert(err.message)
+        })
+      }, 1000)
+    }
+  }
+}
diff --git a/client/js/components/editor-video.vue b/client/js/components/editor-video.vue
index 38e9fef8..50e998ed 100644
--- a/client/js/components/editor-video.vue
+++ b/client/js/components/editor-video.vue
@@ -34,9 +34,9 @@
 
 <script>
   const videoRules = {
-    'youtube': new RegExp(/(?:(?:youtu\.be\/|v\/|vi\/|u\/\w\/|embed\/)|(?:(?:watch)?\?v(?:i)?=|&v(?:i)?=))([^#&?]*).*/, 'i'),
-    'vimeo': new RegExp(/vimeo.com\/(?:channels\/(?:\w+\/)?|groups\/(?:[^/]*)\/videos\/|album\/(?:\d+)\/video\/|)(\d+)(?:$|\/|\?)/, 'i'),
-    'dailymotion': new RegExp(/(?:dailymotion\.com(?:\/embed)?(?:\/video|\/hub)|dai\.ly)\/([0-9a-z]+)(?:[-_0-9a-zA-Z]+(?:#video=)?([a-z0-9]+)?)?/, 'i')
+    'youtube': new RegExp('/(?:(?:youtu\\.be\\/|v\\/|vi\\/|u\\/\\w\\/|embed\\/)|(?:(?:watch)?\\?v(?:i)?=|&v(?:i)?=))([^#&?]*).*/', 'i'),
+    'vimeo': new RegExp('/vimeo.com\\/(?:channels\\/(?:\\w+\\/)?|groups\\/(?:[^/]*)\\/videos\\/|album\\/(?:\\d+)\\/video\\/|)(\\d+)(?:$|\\/|\\?)/', 'i'),
+    'dailymotion': new RegExp('/(?:dailymotion\\.com(?:\\/embed)?(?:\\/video|\\/hub)|dai\\.ly)\\/([0-9a-z]+)(?:[-_0-9a-zA-Z]+(?:#video=)?([a-z0-9]+)?)?/', 'i')
   }
 
   export default {
diff --git a/client/js/components/login.vue b/client/js/components/login.vue
new file mode 100644
index 00000000..d725ce5a
--- /dev/null
+++ b/client/js/components/login.vue
@@ -0,0 +1,70 @@
+<template lang="pug">
+  .login(:class='{ "is-error": error }')
+    .login-container(:class='{ "is-expanded": strategies.length > 1 }')
+      .login-error(v-if='error')
+        strong
+          i.icon-warning-outline
+          | {{ error.title }}
+        span {{ error.message }}
+      .login-providers(v-show='strategies.length > 1')
+        button(v-for='strategy in strategies', :class='{ "is-active": strategy.key === selectedStrategy }', @click='selectStrategy(strategy.key, strategy.useForm)', :title='strategy.title')
+          em(v-html='strategy.icon')
+          span {{ strategy.title }}
+      .login-frame
+        h1 {{ siteTitle }}
+        h2 {{ $t('auth:loginrequired') }}
+        form(method='post', action='/login')
+          input#login-user(type='text', name='email', :placeholder='$t("auth:fields.emailuser")')
+          input#login-pass(type='password', name='password', :placeholder='$t("auth:fields.password")')
+          button.button.is-light-blue.is-fullwidth(type='submit')
+            span {{ $t('auth:actions.login') }}
+    .login-copyright
+      span {{ $t('footer.poweredby') }}
+      a(href='https://wiki.js.org', rel='external', title='Wiki.js') Wiki.js
+</template>
+
+<script>
+export default {
+  name: 'login',
+  data() {
+    return {
+      error: false,
+      strategies: [],
+      selectedStrategy: 'local'
+    }
+  },
+  computed: {
+    siteTitle() {
+      return siteConfig.title
+    }
+  },
+  methods: {
+    selectStrategy(key, useForm) {
+      this.selectedStrategy = key
+      if (!useForm) {
+        window.location.assign(siteConfig.path + '/login/' + key)
+      }
+    },
+    refreshStrategies() {
+      graphQL.query({
+        query: CONSTANTS.GRAPHQL.GQL_QUERY_AUTHENTICATION,
+        variables: {
+          mode: 'active'
+        }
+      }).then(resp => {
+        if (resp.data.authentication) {
+          this.strategies = resp.data.authentication
+        } else {
+          throw new Error('No authentication providers available!')
+        }
+      }).catch(err => {
+        console.error(err)
+      })
+    }
+  },
+  mounted() {
+    this.refreshStrategies()
+  }
+}
+</script>
+
diff --git a/client/js/components/page-loader.vue b/client/js/components/page-loader.vue
index 8f7071e3..e4171b6d 100644
--- a/client/js/components/page-loader.vue
+++ b/client/js/components/page-loader.vue
@@ -5,20 +5,19 @@
       span {{ msg }}
 </template>
 
-<script>
-  export default {
-    name: 'page-loader',
-    props: ['text'],
-    data () {
-      return {}
-    },
-    computed: {
-      msg () { return this.$store.state.pageLoader.msg },
-      isShown () { return this.$store.state.pageLoader.shown }
-    },
-    mounted() {
-      this.$store.commit('pageLoader/msgChange', this.text)
-    }
+<script type='js'>
+export default {
+  name: 'page-loader',
+  props: ['text'],
+  data () {
+    return {}
+  },
+  computed: {
+    msg () { return this.$store.state.pageLoader.msg },
+    isShown () { return this.$store.state.pageLoader.shown }
+  },
+  mounted() {
+    this.$store.commit('pageLoader/msgChange', this.text)
   }
 }
 </script>
diff --git a/client/js/constants/graphql.js b/client/js/constants/graphql.js
new file mode 100644
index 00000000..e189cce7
--- /dev/null
+++ b/client/js/constants/graphql.js
@@ -0,0 +1,22 @@
+import gql from 'graphql-tag'
+
+export default {
+  GQL_QUERY_AUTHENTICATION: gql`
+    query($mode: String!) {
+      authentication(mode:$mode) {
+        key
+        useForm
+        title
+        icon
+      }
+    }
+  `,
+  GQL_QUERY_TRANSLATIONS: gql`
+    query($locale: String!, $namespace: String!) {
+      translations(locale:$locale, namespace:$namespace) {
+        key
+        value
+      }
+    }
+  `
+}
diff --git a/client/js/constants/index.js b/client/js/constants/index.js
new file mode 100644
index 00000000..56e9acc7
--- /dev/null
+++ b/client/js/constants/index.js
@@ -0,0 +1,5 @@
+import GRAPHQL from './graphql'
+
+export default {
+  GRAPHQL
+}
diff --git a/client/js/helpers/index.js b/client/js/helpers/index.js
index 6f802e8b..6335809b 100644
--- a/client/js/helpers/index.js
+++ b/client/js/helpers/index.js
@@ -1,6 +1,7 @@
 'use strict'
 
 const helpers = {
+  _: require('./lodash'),
   common: require('./common'),
   form: require('./form'),
   pages: require('./pages')
diff --git a/client/js/login.js b/client/js/login.js
deleted file mode 100644
index 892e3306..00000000
--- a/client/js/login.js
+++ /dev/null
@@ -1,7 +0,0 @@
-'use strict'
-
-/* global $ */
-
-$(() => {
-  $('#login-user').focus()
-})
diff --git a/client/js/modules/localization.js b/client/js/modules/localization.js
new file mode 100644
index 00000000..2ac94cd7
--- /dev/null
+++ b/client/js/modules/localization.js
@@ -0,0 +1,52 @@
+import i18next from 'i18next'
+import i18nextXHR from 'i18next-xhr-backend'
+import i18nextCache from 'i18next-localstorage-cache'
+import VueI18Next from '@panter/vue-i18next'
+import loSet from 'lodash/set'
+
+/* global siteConfig, graphQL, CONSTANTS */
+
+module.exports = {
+  VueI18Next,
+  init() {
+    i18next
+      .use(i18nextXHR)
+      .use(i18nextCache)
+      .init({
+        backend: {
+          loadPath: '{{lng}}/{{ns}}',
+          parse: (data) => data,
+          ajax: (url, opts, cb, data) => {
+            let langParams = url.split('/')
+            graphQL.query({
+              query: CONSTANTS.GRAPHQL.GQL_QUERY_TRANSLATIONS,
+              variables: {
+                locale: langParams[0],
+                namespace: langParams[1]
+              }
+            }).then(resp => {
+              let ns = {}
+              if (resp.data.translations.length > 0) {
+                resp.data.translations.forEach(entry => {
+                  loSet(ns, entry.key, entry.value)
+                })
+              }
+              return cb(ns, {status: '200'})
+            }).catch(err => {
+              console.error(err)
+              return cb(null, {status: '404'})
+            })
+          }
+        },
+        cache: {
+          enabled: true,
+          expiration: 60 * 60 * 1000
+        },
+        defaultNS: 'common',
+        lng: siteConfig.lang,
+        fallbackLng: siteConfig.lang,
+        ns: ['common', 'admin', 'auth']
+      })
+    return new VueI18Next(i18next)
+  }
+}
diff --git a/client/scss/app.scss b/client/scss/app.scss
index a86c88e8..ab58c08e 100644
--- a/client/scss/app.scss
+++ b/client/scss/app.scss
@@ -15,6 +15,7 @@ $primary: 'indigo';
 @import 'components/button';
 @import 'components/collapsable-nav';
 @import 'components/color-picker';
+@import 'components/config-manager';
 @import 'components/footer';
 @import 'components/form';
 @import 'components/grid';
@@ -43,6 +44,7 @@ $primary: 'indigo';
 @import 'layout/_loader';
 @import 'layout/_rtl';
 
-@import 'pages/_welcome';
+@import 'pages/login';
+@import 'pages/welcome';
 
 @import 'base/print';
diff --git a/client/scss/base/base.scss b/client/scss/base/base.scss
index 6d8a688e..54740abe 100644
--- a/client/scss/base/base.scss
+++ b/client/scss/base/base.scss
@@ -11,10 +11,15 @@ html {
   display: none;
 }
 
-#root {
+#app {
   padding-bottom: 67px;
   position: relative;
   min-height: 100%;
+
+  &.is-fullscreen {
+    width: 100vw;
+    height: 100vh;
+  }
 }
 
 body {
diff --git a/client/scss/components/button.scss b/client/scss/components/button.scss
index 97338a0e..0f5c9a09 100644
--- a/client/scss/components/button.scss
+++ b/client/scss/components/button.scss
@@ -4,7 +4,7 @@
 	border: 1px solid mc('orange','700');
 	border-radius: 3px;
 	display: inline-flex;
-	height: 30px;
+	height: 40px;
 	align-items: center;
 	padding: 0 15px;
 	font-size: 13px;
@@ -61,7 +61,11 @@
 				background-color: mc($color,'800');
 				color: #FFF;
 				animation: none;
-			}
+      }
+
+      &:focus {
+        box-shadow: inset 0 0 0 3px rgba(255,255,255, .4);
+      }
 		}
 
 	}
@@ -74,7 +78,13 @@
 
 	&.is-featured {
 		animation: btnInvertedPulse .6s ease alternate infinite;
-	}
+  }
+
+  &.is-fullwidth {
+    width: 100%;
+    text-align: center;
+    justify-content: center;
+  }
 
 	&.is-disabled, &:disabled {
 		background-color: mc('grey', '300');
@@ -87,7 +97,11 @@
       background-color: mc('grey', '300') !important;
       color: mc('grey', '500') !important;
     }
-	}
+  }
+
+  &.is-small {
+    height: 30px;
+  }
 
 }
 
diff --git a/client/scss/components/config-manager.scss b/client/scss/components/config-manager.scss
new file mode 100644
index 00000000..8ee89d91
--- /dev/null
+++ b/client/scss/components/config-manager.scss
@@ -0,0 +1,61 @@
+.config-manager {
+  .welcome {
+    text-align: center;
+    padding: 50px 0 15px 0;
+    color: mc('grey', '700');
+
+    h2 {
+      margin: 0;
+    }
+
+  }
+
+  i.icon-loader {
+    display: inline-block;
+    color: mc('indigo', '500')
+  }
+  i.icon-check {
+    color: mc('green', '500')
+  }
+  i.icon-square-cross {
+    color: mc('red', '500')
+  }
+  i.icon-warning-outline {
+    color: mc('orange', '500')
+  }
+
+  .tst-welcome-leave-active, .tst-welcome-enter-active {
+    transition: all .5s;
+    overflow-y: hidden;
+  }
+  .tst-welcome-leave, .tst-welcome-enter-to {
+    opacity: 1;
+    max-height: 200px;
+  }
+  .tst-welcome-leave-to, .tst-welcome-enter {
+    opacity: 0;
+    max-height: 0;
+    padding-top: 0;
+  }
+
+  .progress-bar {
+    width: 150px;
+    height: 10px;
+    background-color: mc('indigo', '50');
+    border:1px solid mc('indigo', '100');
+    border-radius: 3px;
+    position: absolute;
+    left: 15px;
+    top: 21px;
+    padding: 1px;
+
+    > div {
+      width: 5px;
+      height: 6px;
+      background-color: mc('indigo', '200');
+      border-radius: 2px;
+      transition: all 1s ease;
+    }
+
+  }
+}
diff --git a/client/scss/login.scss b/client/scss/login.scss
deleted file mode 100644
index 725ce498..00000000
--- a/client/scss/login.scss
+++ /dev/null
@@ -1,13 +0,0 @@
-@charset "utf-8";
-
-$primary: 'indigo';
-
-@import "base/variables";
-@import "base/colors";
-@import "base/reset";
-@import "base/mixins";
-@import "base/fonts";
-@import "base/base";
-
-@import "libs/animate";
-@import 'pages/login';
diff --git a/client/scss/pages/_login.scss b/client/scss/pages/_login.scss
index abfd9c93..be90d44f 100644
--- a/client/scss/pages/_login.scss
+++ b/client/scss/pages/_login.scss
@@ -1,306 +1,264 @@
+.login {
+  background-image: linear-gradient(to right, mc('blue', '400'), mc('blue', '600'));
+  width: 100%;
+  height: 100%;
+  display: flex;
+  align-items: center;
+  justify-content: center;
 
-body {
-	padding: 0;
-	margin: 0;
-	font-family: $core-font-standard;
-	font-size: 14px;
-}
-
-a {
-	color: #FFF;
-	transition: color 0.4s ease;
-	text-decoration: none;
-
-	&:hover {
-		color: mc('orange','600');
-		text-decoration: underline;
-	}
-
-}
-
-#bg {
-	position: fixed;
-	top: 0;
-	left: 0;
-	width: 100%;
-	height: 100%;
-	z-index: 1;
-	background-color: #000;
-
-	> div {
-		background-size: cover;
-		background-position: center center;
-		width: 100%;
-		height: 100%;
-		position: absolute;
-		top: 0;
-		left: 0;
-		opacity: 0;
-		visibility: hidden;
-		transition: opacity 3s ease, visibility 3s;
-		animation: bg 30s linear infinite;
-
-		&:nth-child(1) {
-			animation-delay: 10s;
-		}
-
-		&:nth-child(2) {
-			animation-delay: 20s;
-		}
-
-	}
-
-}
-
-#root {
-	position: fixed;
-	top: 15vh;
-	left: 10vw;
-	z-index: 2;
-	color: #FFF;
-	display: flex;
-	flex-direction: column;
-
-	h1 {
-		font-size: 4rem;
-		font-weight: bold;
-		color: #FFF;
-		padding: 0;
-		margin: 0;
-		animation: headerIntro 3s ease;
-	}
-
-	h2 {
-		font-size: 1.5rem;
-		font-weight: normal;
-		color: rgba(255,255,255,0.7);
-		padding: 0;
-		margin: 0 0 25px 0;
-		animation: headerIntro 3s ease;
-	}
-
-	h3 {
-		font-size: 1.25rem;
-		font-weight: normal;
-		color: #FB8C00;
-		padding: 0;
-		margin: 0;
-		animation: shake 1s ease;
-
-		> .fa {
-			margin-right: 7px;
-		}
-
-	}
-
-	h4 {
-		font-size: 0.8rem;
-		font-weight: normal;
-		color: rgba(255,255,255,0.7);
-		padding: 0;
-		margin: 0 0 15px 0;
-		animation: fadeIn 3s ease;
-	}
-
-	form {
-		display: flex;
-		flex-direction: column;
-	}
-
-	input[type=text], input[type=password] {
-		width: 350px;
-		max-width: 80vw;
-		border: 1px solid rgba(255,255,255,0.3);
-		border-radius: 3px;
-		background-color: rgba(0,0,0,0.2);
-		padding: 0 15px;
-		height: 40px;
-		margin: 0 0 10px 0;
-		color: #FFF;
-		font-weight: bold;
-		font-size: 14px;
-		transition: all 0.4s ease;
-
-		&:focus {
-			outline: none;
-			border-color: mc('orange','600');
-		}
-
-	}
-
-	button {
-		background-color: mc('orange','600');
-		color: #FFF;
-		border: 1px solid lighten(mc('orange','600'), 10%);
-		border-radius: 3px;
-		height: 40px;
-		width: 125px;
-		padding: 0;
-		font-weight: bold;
-		margin: 15px 0 0 0;
-		transition: all 0.4s ease;
-		cursor: pointer;
-
-		span {
-			font-weight: bold;
-		}
-
-		&:focus {
-			outline: none;
-			border-color: #FFF;
-		}
-
-		&:hover {
-			background-color: darken(mc('orange','600'), 10%);
-		}
-
-	}
-
-	#social {
-		margin-top: 25px;
-
-		> span {
-			display: block;
-			font-weight: bold;
-			color: rgba(255,255,255,0.7);
-		}
-
-		button {
-			margin-right: 5px;
-			width: auto;
-			padding: 0 15px;
-
-			> i {
-				margin-right: 10px;
-				font-size: 16px;
-			}
-
-			&.ms {
-				background-color: mc('blue','600');
-				border-color: lighten(mc('blue','600'), 10%);
-
-				&:focus {
-					border-color: #FFF;
-				}
-
-				&:hover {
-					background-color: darken(mc('blue','600'), 10%);
-				}
-
-			}
-
-			&.google {
-				background-color: mc('light-blue','600');
-				border-color: lighten(mc('light-blue','600'), 10%);
-
-				&:focus {
-					border-color: #FFF;
-				}
-
-				&:hover {
-					background-color: darken(mc('light-blue','600'), 10%);
-				}
-
-			}
-
-			&.facebook {
-				background-color: mc('indigo','600');
-				border-color: lighten(mc('indigo','600'), 10%);
-
-				&:focus {
-					border-color: #FFF;
-				}
-
-				&:hover {
-					background-color: darken(mc('indigo','600'), 10%);
-				}
-
-			}
-
-      &.github {
-				background-color: mc('blue-grey','700');
-				border-color: lighten(mc('blue-grey','700'), 10%);
-
-				&:focus {
-					border-color: #FFF;
-				}
-
-				&:hover {
-					background-color: darken(mc('blue-grey','700'), 10%);
-				}
-			}
-
-      &.slack {
-				background-color: mc('purple','700');
-				border-color: lighten(mc('purple','700'), 10%);
-
-				&:focus {
-					border-color: #FFF;
-				}
-
-				&:hover {
-					background-color: darken(mc('purple','700'), 10%);
-				}
-			}
-
-		}
-
-	}
-
-}
-
-#copyright {
-	display: flex;
-	align-items: center;
-	justify-content: flex-start;
-	position: absolute;
-	left: 10vw;
-	bottom: 10vh;
-	z-index: 2;
-	color: rgba(255,255,255,0.5);
-	font-weight: bold;
-
-	.icon {
-		font-size: 1.2rem;
-		margin: 0 8px;
-	}
-
-	a {
-		opacity: 0.75;
-	}
-
-}
-
-@include keyframes(bg) {
-	0% {
-		@include prefix(transform, scale(1,1));
-		visibility: visible;
-		opacity: 0;
-	},
-	5% {
-		opacity: 0.5;
-	},
-	33% {
-		opacity: 0.5;
-	},
-	38% {
-		@include prefix(transform, scale(1.2, 1.2));
-		opacity: 0;
-	},
-	39% {
-		visibility: hidden;
-	}
-	100% {
-		visibility: hidden;
-		opacity: 0;
-	}
-}
-
-@include keyframes(headerIntro) {
-	0% {
-		opacity: 0;
-	}
-	100% {
-		opacity: 1;
-	}
+  &.is-error {
+    background-image: linear-gradient(to right, mc('red', '400'), mc('red', '600'));
+  }
+
+  &::before {
+    content: '';
+    position: absolute;
+    background-image: url('../svg/login-bg.svg');
+    background-position: center bottom;
+    background-size: cover;
+    top: 0;
+    left: 0;
+    width: 100vw;
+    height: 100vh;
+  }
+
+  &-container {
+    position: relative;
+    display: flex;
+    width: 400px;
+    align-items: stretch;
+    box-shadow: 0 14px 28px rgba(0,0,0,0.2);
+    border-radius: 6px;
+
+    &.is-expanded {
+      width: 650px;
+
+      .login-frame {
+        border-radius: 0 6px 6px 0;
+        border-left: none;
+      }
+    }
+
+    @include until($tablet) {
+      width: 350px;
+
+      &.is-expanded {
+        width: 400px;
+      }
+    }
+  }
+
+  &-error {
+    position: absolute;
+    bottom: 105%;
+    width: 100%;
+    min-height: 50px;
+    background-image: radial-gradient(ellipse at top left, rgba(255,255,255,.9) 0%,rgba(255,255,255,.8) 100%);
+    box-shadow: 0 5px 10px rgba(0,0,0,0.2);
+    border-radius: 6px;
+    color: mc('red', '800');
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    padding: 1rem;
+
+    strong {
+      font-weight: 600;
+      text-transform: uppercase;
+      display: block;
+      padding: 0 1rem 0 0;
+      border-right: 1px solid mc('red', '200');
+    }
+    span {
+      padding: 0 0 0 1rem;
+      display: block;
+    }
+  }
+
+  &-providers {
+    display: flex;
+    flex-direction: column;
+    width: 250px;
+
+    border-right: none;
+    border-radius: 6px 0 0 6px;
+    z-index: 1;
+    overflow: hidden;
+
+    @include until($tablet) {
+      width: 50px;
+    }
+
+    button {
+      flex: 1 1;
+      padding: 5px 15px;
+      border: none;
+      color: #FFF;
+      background: linear-gradient(to right, rgba(mc('light-blue', '800'), .7), rgba(mc('light-blue', '800'), 1));
+      border-top: 1px solid rgba(mc('light-blue', '900'), .5);
+      font-family: $core-font-standard;
+      font-weight: 600;
+      text-align: left;
+      min-height: 40px;
+      display: flex;
+      justify-content: flex-start;
+      align-items: center;
+      transition: all .4s ease;
+
+      &:focus {
+        outline: none;
+      }
+
+      @include until($tablet) {
+        justify-content: center;
+      }
+
+      &:hover {
+        background-color: mc('light-blue', '900');
+      }
+
+      &:first-child {
+        border-top: none;
+
+        &.is-active {
+          border-top: 1px solid rgba(255,255,255, .5);
+        }
+      }
+
+      &.is-active {
+        background-image: linear-gradient(to right, rgba(255,255,255,1) 0%,rgba(255,255,255,.77) 100%);
+        color: mc('light-blue', '700');
+        cursor: default;
+
+        &:hover {
+          background-color: transparent;
+        }
+
+        svg path {
+          fill: mc('light-blue', '800');
+        }
+      }
+
+      i {
+        margin-right: 10px;
+        font-size: 16px;
+
+        @include until($tablet) {
+          margin-right: 0;
+          font-size: 20px;
+        }
+      }
+
+      svg {
+        margin-right: 10px;
+        width: auto;
+        height: 20px;
+        max-width: 18px;
+        max-height: 20px;
+
+        path {
+          fill: #FFF;
+        }
+
+        @include until($tablet) {
+          margin-right: 0;
+          font-size: 20px;
+        }
+      }
+
+      span {
+        font-weight: 600;
+
+        @include until($tablet) {
+          display: none;
+        }
+      }
+    }
+  }
+
+  &-frame {
+    background-image: radial-gradient(circle at top center, rgba(255,255,255,1) 5%,rgba(255,255,255,.6) 100%);
+    border: 1px solid rgba(255,255,255, .5);
+    border-radius: 6px;
+    width: 400px;
+    padding: 1rem;
+    color: mc('grey', '700');
+    display: flex;
+    justify-content: center;
+    flex-direction: column;
+    text-align: center;
+
+    @include until($tablet) {
+      width: 350px;
+    }
+
+    h1 {
+      font-size: 2rem;
+      font-weight: 600;
+      color: mc('light-blue', '700');
+      text-shadow: 1px 1px 0 #FFF;
+      padding: 0;
+      margin: 0;
+    }
+
+    h2 {
+      font-size: 1.5rem;
+      font-weight: 300;
+      color: mc('grey', '700');
+      text-shadow: 1px 1px 0 #FFF;
+      padding: 0;
+      margin: 0 0 25px 0;
+    }
+
+    form {
+      display: flex;
+      flex-direction: column;
+    }
+
+    input[type=text], input[type=password] {
+      width: 100%;
+      border: 1px solid #FFF;
+      border-radius: 3px;
+      background-color: rgba(255,255,255,.9);
+      box-shadow: inset 0 0 0 3px rgba(255,255,255, .25);
+      padding: 0 15px;
+      height: 40px;
+      margin: 0 0 10px 0;
+      color: mc('grey', '700');
+      font-weight: 600;
+      font-size: .8rem;
+      transition: all 0.4s ease;
+      text-align: center;
+
+      &:focus {
+        outline: none;
+        border-color: mc('light-blue','500');
+        background-color: rgba(255,255,255,1);
+        box-shadow: inset 0 0 0 3px rgba(mc('light-blue','500'), .25);
+        color: mc('light-blue', '800');
+      }
+
+    }
+
+  }
+
+  &-copyright {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    position: absolute;
+    left: 0;
+    bottom: 10vh;
+    width: 100%;
+    z-index: 2;
+    color: mc('grey', '500');
+    font-weight: 400;
+
+    a {
+      font-weight: 600;
+      color: mc('light-blue', '500');
+      margin-left: .25rem;
+    }
+
+  }
 }
diff --git a/config.sample.yml b/config.sample.yml
index aa1e7c0a..5421d5a8 100644
--- a/config.sample.yml
+++ b/config.sample.yml
@@ -5,23 +5,9 @@
 # https://docs.requarks.io/wiki/install
 
 # ---------------------------------------------------------------------
-# Title of this site
+# Port the main server should listen to
 # ---------------------------------------------------------------------
 
-title: Wiki
-
-# ---------------------------------------------------------------------
-# Full public path to the site, without the trailing slash
-# ---------------------------------------------------------------------
-# INCLUDE CLIENT PORT IF NOT 80/443!
-
-host: http://localhost
-
-# ---------------------------------------------------------------------
-# Port the main server should listen to (80 by default)
-# ---------------------------------------------------------------------
-# To use process.env.PORT, comment the line below:
-
 port: 80
 
 # ---------------------------------------------------------------------
@@ -33,140 +19,38 @@ paths:
   data: ./data
 
 # ---------------------------------------------------------------------
-# Upload Limits
-# ---------------------------------------------------------------------
-# In megabytes (MB)
-
-uploads:
-  maxImageFileSize: 3
-  maxOtherFileSize: 100
-
-# ---------------------------------------------------------------------
-# Site Language
-# ---------------------------------------------------------------------
-# Possible values: en, de, es, fa, fr, ja, ko, nl, pt, ru, sr, tr or zh
-
-lang: en
-
-# Enable for right to left languages (e.g. arabic):
-langRtl: false
-
-# ---------------------------------------------------------------------
-# Site Authentication
+# Database
 # ---------------------------------------------------------------------
 
-public: false
-
-auth:
-  defaultReadAccess: false
-  local:
-    enabled: true
-  google:
-    enabled: true
-    clientId: GOOGLE_CLIENT_ID
-    clientSecret: GOOGLE_CLIENT_SECRET
-  microsoft:
-    enabled: true
-    clientId: MS_APP_ID
-    clientSecret: MS_APP_SECRET
-  facebook:
-    enabled: false
-    clientId: FACEBOOK_APP_ID
-    clientSecret: FACEBOOK_APP_SECRET
-  github:
-    enabled: false
-    clientId: GITHUB_CLIENT_ID
-    clientSecret: GITHUB_CLIENT_SECRET
-  slack:
-    enabled: false
-    clientId: 'SLACK_CLIENT_ID'
-    clientSecret: 'SLACK_CLIENT_SECRET'
-  ldap:
-    enabled: false
-    url: ldap://serverhost:389
-    bindDn: cn='root'
-    bindCredentials: BIND_PASSWORD
-    searchBase: o=users,o=example.com
-    searchFilter: (uid={{username}})
-    tlsEnabled: false
-    tlsCertPath: C:\example\root_ca_cert.crt
-  azure:
-    enabled: false
-    clientId: APP_ID
-    clientSecret: APP_SECRET_KEY
-    resource: '00000002-0000-0000-c000-000000000000'
-    tenant: 'YOUR_TENANT.onmicrosoft.com'
+db:
+  host: localhost
+  port: 5432
+  user: wikijs
+  pass: wikijsrocks
+  db: wiki
 
 # ---------------------------------------------------------------------
-# Secret key to use when encrypting sessions
-# ---------------------------------------------------------------------
-# Use a long and unique random string (256-bit keys are perfect!)
-
-sessionSecret: 1234567890abcdefghijklmnopqrstuvxyz
-
-# ---------------------------------------------------------------------
-# Database Connection String
-# ---------------------------------------------------------------------
-# You can also use an ENV variable by using $ENV_VAR_NAME as the value
-
-db: mongodb://localhost:27017/wiki
-
-# ---------------------------------------------------------------------
-# Git Connection Info
+# Redis
 # ---------------------------------------------------------------------
 
-git:
-  url: https://github.com/Organization/Repo
-  branch: master
-  auth:
-
-    # Type: basic or ssh
-    type: ssh
-
-    # Only for Basic authentication:
-    username: marty
-    password: MartyMcFly88
-
-    # Only for SSH authentication:
-    privateKey: /etc/wiki/keys/git.pem
-
-    sslVerify: true
-
-  # Default email to use as commit author
-  serverEmail: marty@example.com
-
-  # Whether to use user email as author in commits
-  showUserEmail: true
+redis:
+  host: localhost
+  port: 6379
+  db: 0
+  password: null
 
 # ---------------------------------------------------------------------
-# Features
+# Background Workers
 # ---------------------------------------------------------------------
-# You can enable / disable specific features below
+# Leave 0 for auto based on CPU cores
 
-features:
-  linebreaks: true
-  mathjax: true
+workers: 0
 
 # ---------------------------------------------------------------------
-# External Logging
+# High Availability
 # ---------------------------------------------------------------------
+# Read the docs BEFORE changing these settings!
 
-externalLogging:
-  bugsnag: false
-  loggly: false
-  papertrail: false
-  rollbar: false
-  sentry: false
-
-# ---------------------------------------------------------------------
-# Color Theme
-# ---------------------------------------------------------------------
-
-theme:
-  primary: indigo
-  alt: blue-grey
-  viewSource: all # all | write | false
-  footer: blue-grey
-  code:
-    dark: true
-    colorize: true
+ha:
+  nodeuid: primary
+  readonly: false
diff --git a/npm/README.md b/npm/README.md
deleted file mode 100644
index d482407e..00000000
--- a/npm/README.md
+++ /dev/null
@@ -1,14 +0,0 @@
-![Wiki.js](https://raw.githubusercontent.com/Requarks/wiki-site/1.0/assets/images/logo.png)
-
-# Wiki.js
-
-[![npm](https://img.shields.io/npm/v/wiki.js.svg?style=flat-square)](https://github.com/Requarks)
-[![Release](https://img.shields.io/github/release/Requarks/wiki.svg?style=flat-square&maxAge=3600)](https://github.com/Requarks/wiki/releases)
-[![License](https://img.shields.io/badge/license-AGPLv3-blue.svg?style=flat-square)](https://github.com/requarks/wiki/blob/master/LICENSE)
-
-This npm package is an installer for Wiki.js.  
-For information about Wiki.js, including detailed installation steps, read the following links:
-
-- [Official Website](https://wiki.js.org/)
-- [Installation Guide](https://wiki.js.org/get-started.html)
-- [GitHub Repository](https://github.com/Requarks/wiki)
diff --git a/npm/install.js b/npm/install.js
deleted file mode 100644
index cd0a0511..00000000
--- a/npm/install.js
+++ /dev/null
@@ -1,25 +0,0 @@
-'use strict'
-
-// =====================================================
-// Wiki.js
-// Installation Script
-// =====================================================
-
-const path = require('path')
-const spawn = require('child_process').spawn
-const installDir = path.resolve(__dirname, '../..')
-const cmd = (process.platform !== 'win32')
-  ? 'curl -s -S -o- https://wiki.js.org/install.sh | bash'
-  : `PowerShell.exe -NoProfile -ExecutionPolicy Bypass -Command "iex ((New-Object System.Net.WebClient).DownloadString('https://wiki.js.org/install.ps1'))"`
-
-console.info(`Executing installation script for ${process.platform} platform...`)
-
-let inst = spawn(cmd, [], {
-  cwd: installDir,
-  env: process.env,
-  shell: true,
-  stdio: 'inherit',
-  detached: true
-})
-
-inst.unref()
diff --git a/npm/package.json b/npm/package.json
deleted file mode 100644
index 2098e56c..00000000
--- a/npm/package.json
+++ /dev/null
@@ -1,32 +0,0 @@
-{
-  "name": "wiki.js",
-  "version": "1.0.5-rev.1",
-  "description": "A modern, lightweight and powerful wiki app built on NodeJS, Git and Markdown",
-  "main": "install.js",
-  "scripts": {
-    "test": "exit 1",
-    "postinstall": "node install.js"
-  },
-  "repository": {
-    "type": "git",
-    "url": "git+https://github.com/Requarks/wiki.git"
-  },
-  "keywords": [
-    "wiki",
-    "wikis",
-    "wikijs",
-    "wiki.js",
-    "wiki-js",
-    "docs",
-    "documentation",
-    "markdown",
-    "guides"
-  ],
-  "author": "Nicolas Giard",
-  "license": "AGPL-3.0",
-  "bugs": {
-    "url": "https://github.com/Requarks/wiki/issues"
-  },
-  "homepage": "https://github.com/Requarks/wiki#readme",
-  "dependencies": {}
-}
diff --git a/package.json b/package.json
index ef84b9e1..692165db 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "wiki",
-  "version": "1.0.11",
+  "version": "2.0.0",
   "description": "A modern, lightweight and powerful wiki app built on NodeJS, Git and Markdown",
   "main": "wiki.js",
   "scripts": {
@@ -9,7 +9,6 @@
     "restart": "node wiki restart",
     "build": "node tools/fuse",
     "dev": "node tools/fuse -d",
-    "dev-configure": "node tools/fuse -c",
     "test": "jest",
     "postinstall": "opencollective postinstall"
   },
@@ -38,135 +37,143 @@
     "node": ">=6.11.1"
   },
   "dependencies": {
-    "auto-load": "~3.0.0",
-    "axios": "~0.16.2",
-    "bcryptjs-then": "~1.0.1",
-    "bluebird": "~3.5.0",
-    "body-parser": "~1.17.2",
-    "bunyan": "~1.8.12",
-    "cheerio": "~1.0.0-rc.2",
-    "child-process-promise": "~2.2.1",
-    "chokidar": "~1.7.0",
-    "compression": "~1.7.0",
-    "connect-flash": "~0.1.1",
-    "connect-mongo": "~1.3.2",
-    "cookie-parser": "~1.4.3",
-    "cron": "~1.2.1",
-    "diff2html": "~2.3.0",
-    "execa": "~0.8.0",
-    "express": "~4.15.4",
+    "apollo-server-express": "1.1.3",
+    "auto-load": "3.0.0",
+    "axios": "0.16.2",
+    "bcryptjs-then": "1.0.1",
+    "bluebird": "3.5.1",
+    "body-parser": "1.18.2",
+    "bull": "3.3.0",
+    "bunyan": "1.8.12",
+    "cheerio": "1.0.0-rc.2",
+    "child-process-promise": "2.2.1",
+    "chokidar": "1.7.0",
+    "compression": "1.7.1",
+    "connect-flash": "0.1.1",
+    "connect-redis": "3.3.2",
+    "cookie-parser": "1.4.3",
+    "diff2html": "2.3.1",
+    "dotize": "^0.2.0",
+    "execa": "0.8.0",
+    "express": "4.16.1",
     "express-brute": "1.0.1",
-    "express-brute-mongoose": "~0.0.9",
-    "express-session": "~1.15.5",
-    "file-type": "~6.1.0",
-    "filesize.js": "~1.0.2",
-    "follow-redirects": "~1.2.4",
-    "fs-extra": "~4.0.1",
-    "git-wrapper2-promise": "~0.2.9",
-    "highlight.js": "~9.12.0",
-    "i18next": "~9.0.0",
-    "i18next-express-middleware": "~1.0.5",
-    "i18next-node-fs-backend": "~1.0.0",
-    "image-size": "~0.6.0",
-    "jimp": "~0.2.28",
-    "js-yaml": "~3.9.1",
-    "jsonwebtoken": "~7.4.3",
-    "klaw": "~2.1.0",
-    "levelup": "~1.3.9",
-    "lodash": "~4.17.4",
-    "markdown-it": "~8.4.0",
-    "markdown-it-abbr": "~1.0.4",
-    "markdown-it-anchor": "~4.0.0",
-    "markdown-it-attrs": "~1.1.0",
-    "markdown-it-emoji": "~1.4.0",
-    "markdown-it-expand-tabs": "~1.0.12",
+    "express-brute-redis": "0.0.1",
+    "express-session": "1.15.6",
+    "file-type": "6.2.0",
+    "filesize.js": "1.0.2",
+    "follow-redirects": "1.2.5",
+    "fs-extra": "4.0.2",
+    "git-wrapper2-promise": "0.2.9",
+    "graphql": "0.10.5",
+    "graphql-tools": "2.2.1",
+    "highlight.js": "9.12.0",
+    "i18next": "9.1.0",
+    "i18next-express-middleware": "1.0.7",
+    "i18next-localstorage-cache": "1.1.1",
+    "i18next-node-fs-backend": "1.0.0",
+    "image-size": "0.6.1",
+    "ioredis": "3.1.4",
+    "jimp": "0.2.28",
+    "js-yaml": "3.10.0",
+    "jsonwebtoken": "8.0.1",
+    "klaw": "2.1.0",
+    "lodash": "4.17.4",
+    "markdown-it": "8.4.0",
+    "markdown-it-abbr": "1.0.4",
+    "markdown-it-anchor": "4.0.0",
+    "markdown-it-attrs": "1.2.0",
+    "markdown-it-emoji": "1.4.0",
+    "markdown-it-expand-tabs": "1.0.12",
     "markdown-it-external-links": "0.0.6",
-    "markdown-it-footnote": "~3.0.1",
-    "markdown-it-mathjax": "~2.0.0",
-    "markdown-it-task-lists": "~2.0.1",
-    "mathjax-node": "~1.2.0",
-    "memdown": "~1.2.4",
-    "mime-types": "~2.1.16",
-    "moment": "~2.18.1",
-    "moment-timezone": "~0.5.13",
-    "mongodb": "~2.2.31",
-    "mongoose": "~4.11.9",
-    "multer": "~1.3.0",
-    "node-2fa": "~1.1.2",
-    "node-graceful": "~0.2.3",
-    "opencollective": "~1.0.3",
-    "ora": "~1.3.0",
-    "passport": "~0.4.0",
+    "markdown-it-footnote": "3.0.1",
+    "markdown-it-mathjax": "2.0.0",
+    "markdown-it-task-lists": "2.0.1",
+    "mathjax-node": "1.2.1",
+    "mime-types": "2.1.17",
+    "moment": "2.18.1",
+    "moment-timezone": "0.5.13",
+    "multer": "1.3.0",
+    "node-2fa": "1.1.2",
+    "node-graceful": "0.2.3",
+    "ora": "1.3.0",
+    "passport": "0.4.0",
     "passport-azure-ad-oauth2": "0.0.4",
-    "passport-facebook": "~2.1.1",
-    "passport-github2": "~0.1.10",
-    "passport-google-oauth20": "~1.0.0",
-    "passport-ldapauth": "~2.0.0",
-    "passport-local": "~1.0.0",
+    "passport-facebook": "2.1.1",
+    "passport-github2": "0.1.11",
+    "passport-google-oauth20": "1.0.0",
+    "passport-ldapauth": "2.0.0",
+    "passport-local": "1.0.0",
     "passport-slack": "0.0.7",
-    "passport-windowslive": "~1.0.2",
-    "passport.socketio": "~3.7.0",
-    "pm2": "~2.6.1",
-    "pug": "~2.0.0-rc.3",
-    "read-chunk": "~2.1.0",
-    "remove-markdown": "~0.2.2",
-    "request": "~2.81.0",
-    "search-index-adder": "~0.3.9",
-    "search-index-searcher": "~0.2.10",
-    "semver": "~5.4.1",
-    "serve-favicon": "~2.4.3",
-    "simplemde": "~1.11.2",
-    "socket.io": "~2.0.2",
-    "stopword": "~0.1.6",
-    "stream-to-promise": "~2.2.0",
-    "tar": "~4.0.1",
-    "through2": "~2.0.3",
-    "validator": "~8.1.0",
-    "validator-as-promised": "~1.0.2",
-    "winston": "~2.3.1",
-    "yargs": "~8.0.1"
+    "passport-windowslive": "1.0.2",
+    "pg": "6.4.2",
+    "pg-hstore": "2.3.2",
+    "pg-promise": "6.10.3",
+    "pm2": "2.7.1",
+    "pug": "2.0.0-rc.4",
+    "qr-image": "3.2.0",
+    "read-chunk": "2.1.0",
+    "remove-markdown": "0.2.2",
+    "request": "2.83.0",
+    "semver": "5.4.1",
+    "sequelize": "4.13.5",
+    "serve-favicon": "2.4.5",
+    "simplemde": "1.11.2",
+    "stream-to-promise": "2.2.0",
+    "tar": "4.0.1",
+    "through2": "2.0.3",
+    "validator": "9.0.0",
+    "validator-as-promised": "1.0.2",
+    "winston": "2.4.0",
+    "yargs": "9.0.1"
   },
   "devDependencies": {
-    "@glimpse/glimpse": "~0.22.15",
-    "@panter/vue-i18next": "~0.5.0",
-    "babel-cli": "~6.26.0",
-    "babel-jest": "~20.0.3",
-    "babel-plugin-transform-object-assign": "~6.22.0",
-    "babel-preset-es2015": "~6.24.1",
-    "brace": "~0.10.0",
-    "colors": "~1.1.2",
-    "consolidate": "~0.14.5",
-    "eslint": "~4.5.0",
-    "eslint-config-standard": "~10.2.1",
-    "eslint-plugin-import": "~2.7.0",
-    "eslint-plugin-node": "~5.1.0",
-    "eslint-plugin-promise": "~3.5.0",
-    "eslint-plugin-standard": "~3.0.1",
-    "fuse-box": "~2.2.2",
-    "i18next-xhr-backend": "~1.4.2",
-    "jest": "~20.0.4",
-    "jest-junit": "~3.1.0",
-    "jquery": "~3.2.1",
-    "jquery-contextmenu": "~2.5.0",
-    "jquery-simple-upload": "~1.0.0",
-    "jquery-smooth-scroll": "~2.2.0",
-    "jquery-sticky": "~1.0.4",
-    "lodash-cli": "~4.17.4",
-    "lodash-es": "~4.17.4",
-    "node-sass": "~4.5.3",
-    "nodemon": "~1.11.0",
-    "pug-lint": "~2.4.0",
-    "twemoji-awesome": "~1.0.6",
-    "typescript": "~2.5.2",
-    "uglify-es": "~3.0.28",
-    "vee-validate": "~2.0.0-rc.14",
-    "vue": "~2.4.2",
-    "vue-clipboards": "~1.1.0",
-    "vue-lodash": "~1.0.3",
-    "vue-resource": "~1.3.4",
-    "vue-template-compiler": "~2.4.2",
-    "vue-template-es2015-compiler": "~1.5.3",
-    "vuex": "~2.4.0"
+    "@glimpse/glimpse": "0.22.15",
+    "@panter/vue-i18next": "0.6.1",
+    "apollo-client": "^1.9.3",
+    "autoprefixer": "7.1.5",
+    "babel-cli": "6.26.0",
+    "babel-core": "6.26.0",
+    "babel-jest": "21.2.0",
+    "babel-preset-env": "1.6.0",
+    "babel-preset-es2015": "6.24.1",
+    "babel-preset-stage-2": "6.24.1",
+    "brace": "0.10.0",
+    "colors": "1.1.2",
+    "consolidate": "0.14.5",
+    "eslint": "4.8.0",
+    "eslint-config-requarks": "1.0.7",
+    "eslint-config-standard": "10.2.1",
+    "eslint-plugin-import": "2.7.0",
+    "eslint-plugin-node": "5.2.0",
+    "eslint-plugin-promise": "3.5.0",
+    "eslint-plugin-standard": "3.0.1",
+    "fuse-box": "2.3.3",
+    "graphql-tag": "^2.4.2",
+    "i18next-xhr-backend": "1.4.3",
+    "jest": "21.2.1",
+    "jquery": "3.2.1",
+    "jquery-contextmenu": "2.6.2",
+    "jquery-simple-upload": "1.0.0",
+    "js-cookie": "2.1.4",
+    "node-sass": "4.5.3",
+    "nodemon": "1.12.1",
+    "postcss-selector-parser": "2.2.3",
+    "pug-lint": "2.5.0",
+    "twemoji-awesome": "1.0.6",
+    "typescript": "2.5.3",
+    "uglify-es": "3.1.3",
+    "vee-validate": "2.0.0-rc.18",
+    "vue": "2.4.4",
+    "vue-clipboards": "1.1.0",
+    "vue-hot-reload-api": "2.1.1",
+    "vue-lodash": "1.0.4",
+    "vue-material": "^0.7.5",
+    "vue-resource": "1.3.4",
+    "vue-simple-breakpoints": "1.0.2",
+    "vue-template-compiler": "2.4.4",
+    "vue-template-es2015-compiler": "1.5.3",
+    "vuex": "2.4.1",
+    "vuex-persistedstate": "2.0.0"
   },
   "jest": {
     "testResultsProcessor": "./node_modules/jest-junit",
diff --git a/server/agent.js b/server/agent.js
deleted file mode 100644
index 38efd466..00000000
--- a/server/agent.js
+++ /dev/null
@@ -1,222 +0,0 @@
-// ===========================================
-// Wiki.js - Background Agent
-// 1.0.0
-// Licensed under AGPLv3
-// ===========================================
-
-const path = require('path')
-const ROOTPATH = process.cwd()
-const SERVERPATH = path.join(ROOTPATH, 'server')
-
-global.ROOTPATH = ROOTPATH
-global.SERVERPATH = SERVERPATH
-const IS_DEBUG = process.env.NODE_ENV === 'development'
-
-let appconf = require('./libs/config')()
-global.appconfig = appconf.config
-global.appdata = appconf.data
-
-// ----------------------------------------
-// Load Winston
-// ----------------------------------------
-
-global.winston = require('./libs/logger')(IS_DEBUG, 'AGENT')
-
-// ----------------------------------------
-// Load global modules
-// ----------------------------------------
-
-global.winston.info('Background Agent is initializing...')
-
-global.db = require('./libs/db').init()
-global.upl = require('./libs/uploads-agent').init()
-global.git = require('./libs/git').init()
-global.entries = require('./libs/entries').init()
-global.lang = require('i18next')
-global.mark = require('./libs/markdown')
-
-// ----------------------------------------
-// Load modules
-// ----------------------------------------
-
-const moment = require('moment')
-const Promise = require('bluebird')
-const fs = Promise.promisifyAll(require('fs-extra'))
-const klaw = require('klaw')
-const Cron = require('cron').CronJob
-const i18nBackend = require('i18next-node-fs-backend')
-
-const entryHelper = require('./helpers/entry')
-
-// ----------------------------------------
-// Localization Engine
-// ----------------------------------------
-
-global.lang
-  .use(i18nBackend)
-  .init({
-    load: 'languageOnly',
-    ns: ['common', 'admin', 'auth', 'errors', 'git'],
-    defaultNS: 'common',
-    saveMissing: false,
-    preload: [appconfig.lang],
-    lng: appconfig.lang,
-    fallbackLng: 'en',
-    backend: {
-      loadPath: path.join(SERVERPATH, 'locales/{{lng}}/{{ns}}.json')
-    }
-  })
-
-// ----------------------------------------
-// Start Cron
-// ----------------------------------------
-
-let job
-let jobIsBusy = false
-let jobUplWatchStarted = false
-
-global.db.onReady.then(() => {
-  return global.db.Entry.remove({})
-}).then(() => {
-  job = new Cron({
-    cronTime: '0 */5 * * * *',
-    onTick: () => {
-      // Make sure we don't start two concurrent jobs
-
-      if (jobIsBusy) {
-        global.winston.warn('Previous job has not completed gracefully or is still running! Skipping for now. (This is not normal, you should investigate)')
-        return
-      }
-      global.winston.info('Running all jobs...')
-      jobIsBusy = true
-
-      // Prepare async job collector
-
-      let jobs = []
-      let repoPath = path.resolve(ROOTPATH, appconfig.paths.repo)
-      let dataPath = path.resolve(ROOTPATH, appconfig.paths.data)
-      let uploadsTempPath = path.join(dataPath, 'temp-upload')
-
-      // ----------------------------------------
-      // REGULAR JOBS
-      // ----------------------------------------
-
-      //* ****************************************
-      // -> Sync with Git remote
-      //* ****************************************
-
-      jobs.push(global.git.resync().then(() => {
-        // -> Stream all documents
-
-        let cacheJobs = []
-        let jobCbStreamDocsResolve = null
-        let jobCbStreamDocs = new Promise((resolve, reject) => {
-          jobCbStreamDocsResolve = resolve
-        })
-
-        klaw(repoPath).on('data', function (item) {
-          if (path.extname(item.path) === '.md' && path.basename(item.path) !== 'README.md') {
-            let entryPath = entryHelper.parsePath(entryHelper.getEntryPathFromFullPath(item.path))
-            let cachePath = entryHelper.getCachePath(entryPath)
-
-            // -> Purge outdated cache
-
-            cacheJobs.push(
-              fs.statAsync(cachePath).then((st) => {
-                return moment(st.mtime).isBefore(item.stats.mtime) ? 'expired' : 'active'
-              }).catch((err) => {
-                return (err.code !== 'EEXIST') ? err : 'new'
-              }).then((fileStatus) => {
-                // -> Delete expired cache file
-
-                if (fileStatus === 'expired') {
-                  return fs.unlinkAsync(cachePath).return(fileStatus)
-                }
-
-                return fileStatus
-              }).then((fileStatus) => {
-                // -> Update cache and search index
-
-                if (fileStatus !== 'active') {
-                  return global.entries.updateCache(entryPath).then(entry => {
-                    process.send({
-                      action: 'searchAdd',
-                      content: entry
-                    })
-                    return true
-                  })
-                }
-
-                return true
-              })
-            )
-          }
-        }).on('end', () => {
-          jobCbStreamDocsResolve(Promise.all(cacheJobs))
-        })
-
-        return jobCbStreamDocs
-      }))
-
-      //* ****************************************
-      // -> Clear failed temporary upload files
-      //* ****************************************
-
-      jobs.push(
-        fs.readdirAsync(uploadsTempPath).then((ls) => {
-          let fifteenAgo = moment().subtract(15, 'minutes')
-
-          return Promise.map(ls, (f) => {
-            return fs.statAsync(path.join(uploadsTempPath, f)).then((s) => { return { filename: f, stat: s } })
-          }).filter((s) => { return s.stat.isFile() }).then((arrFiles) => {
-            return Promise.map(arrFiles, (f) => {
-              if (moment(f.stat.ctime).isBefore(fifteenAgo, 'minute')) {
-                return fs.unlinkAsync(path.join(uploadsTempPath, f.filename))
-              } else {
-                return true
-              }
-            })
-          })
-        })
-      )
-
-      // ----------------------------------------
-      // Run
-      // ----------------------------------------
-
-      Promise.all(jobs).then(() => {
-        global.winston.info('All jobs completed successfully! Going to sleep for now.')
-
-        if (!jobUplWatchStarted) {
-          jobUplWatchStarted = true
-          global.upl.initialScan().then(() => {
-            job.start()
-          })
-        }
-
-        return true
-      }).catch((err) => {
-        global.winston.error('One or more jobs have failed: ', err)
-      }).finally(() => {
-        jobIsBusy = false
-      })
-    },
-    start: false,
-    timeZone: 'UTC',
-    runOnInit: true
-  })
-})
-
-// ----------------------------------------
-// Shutdown gracefully
-// ----------------------------------------
-
-process.on('disconnect', () => {
-  global.winston.warn('Lost connection to main server. Exiting...')
-  job.stop()
-  process.exit()
-})
-
-process.on('exit', () => {
-  job.stop()
-})
diff --git a/server/app/data.yml b/server/app/data.yml
index 17c1e685..129dc9b9 100644
--- a/server/app/data.yml
+++ b/server/app/data.yml
@@ -5,67 +5,49 @@
 name: Wiki.js
 defaults:
   config:
-    title: Wiki
-    host: http://localhost
     port: 80
     paths:
       repo: ./repo
       data: ./data
-    uploads:
-      maxImageFileSize: 3,
-      maxOtherFileSize: 100
-    lang: en
-    langRtl: false
-    public: false
-    auth:
-      defaultReadAccess: false
-      local:
-        enabled: true
-      microsoft:
-        enabled: false
-      google:
-        enabled: false
-      facebook:
-        enabled: false
-      github:
-        enabled: false
-      slack:
-        enabled: false
-      ldap:
-        enabled: false
-      azure:
-        enabled: false
-    db: mongodb://localhost/wiki
-    sessionSecret: null
-    admin: null
-    git:
-      url: null
-      branch: master
-      auth:
-        type: basic
-        username: null
-        password: null
-        privateKey: null
-        sslVerify: true
-      serverEmail: wiki@example.com
-      showUserEmail: true
-    features:
-      linebreaks: true
-      mathjax: true
-    externalLogging:
-      bugsnap: false
-      loggly: false
-      papertrail: false
-      rollbar: false
-      sentry: false
-    theme:
-      primary: indigo
-      alt: blue-grey
-      footer: blue-grey
-      viewSource: false
-      code:
-        dark: true
-        colorize: true
+    db:
+      host: localhost
+      port: 5432
+      user: wikijs
+      pass: wikijsrocks
+      db: wiki
+    redis:
+      host: localhost
+      port: 6379
+      db: 0
+      password: null
+    workers: 0
+    ha:
+      nodeuid: primary
+      readonly: false
+    site:
+      path: ''
+      lang: en
+    title: Wiki.js
+configNamespaces:
+  - auth
+  - features
+  - git
+  - logging
+  - site
+  - theme
+  - uploads
+queues:
+  - gitSync
+  - uplClearTemp
+authProviders:
+  - local
+  - microsoft
+  - google
+  - facebook
+  - github
+  - slack
+  - ldap
+  - azure
 colors:
   - red
   - pink
@@ -108,6 +90,12 @@ langs:
   -
     id: ko
     name: Korean - 한국어
+  -
+    id: fa
+    name: Persian (Fārsi) - فارسی
+  -
+    id: pt
+    name: Portuguese - Português
   -
     id: ru
     name: Russian - Русский
diff --git a/server/authentication/azure.js b/server/authentication/azure.js
new file mode 100644
index 00000000..70e23cc4
--- /dev/null
+++ b/server/authentication/azure.js
@@ -0,0 +1,37 @@
+'use strict'
+
+/* global wiki */
+
+// ------------------------------------
+// Azure AD Account
+// ------------------------------------
+
+const AzureAdOAuth2Strategy = require('passport-azure-ad-oauth2').Strategy
+
+module.exports = {
+  key: 'azure',
+  title: 'Azure Active Directory',
+  useForm: false,
+  props: ['clientId', 'clientSecret', 'callbackURL', 'resource', 'tenant'],
+  init (passport, conf) {
+    const jwt = require('jsonwebtoken')
+    passport.use('azure_ad_oauth2',
+      new AzureAdOAuth2Strategy({
+        clientID: conf.clientId,
+        clientSecret: conf.clientSecret,
+        callbackURL: conf.callbackURL,
+        resource: conf.resource,
+        tenant: conf.tenant
+      }, (accessToken, refreshToken, params, profile, cb) => {
+        let waadProfile = jwt.decode(params.id_token)
+        waadProfile.id = waadProfile.oid
+        waadProfile.provider = 'azure'
+        wiki.db.User.processProfile(waadProfile).then((user) => {
+          return cb(null, user) || true
+        }).catch((err) => {
+          return cb(err, null) || true
+        })
+      }
+      ))
+  }
+}
diff --git a/server/authentication/facebook.js b/server/authentication/facebook.js
new file mode 100644
index 00000000..24b31416
--- /dev/null
+++ b/server/authentication/facebook.js
@@ -0,0 +1,32 @@
+'use strict'
+
+/* global wiki */
+
+// ------------------------------------
+// Facebook Account
+// ------------------------------------
+
+const FacebookStrategy = require('passport-facebook').Strategy
+
+module.exports = {
+  key: 'facebook',
+  title: 'Facebook',
+  useForm: false,
+  props: ['clientId', 'clientSecret', 'callbackURL'],
+  init (passport, conf) {
+    passport.use('facebook',
+      new FacebookStrategy({
+        clientID: conf.clientId,
+        clientSecret: conf.clientSecret,
+        callbackURL: conf.callbackURL,
+        profileFields: ['id', 'displayName', 'email']
+      }, function (accessToken, refreshToken, profile, cb) {
+        wiki.db.User.processProfile(profile).then((user) => {
+          return cb(null, user) || true
+        }).catch((err) => {
+          return cb(err, null) || true
+        })
+      }
+      ))
+  }
+}
diff --git a/server/authentication/github.js b/server/authentication/github.js
new file mode 100644
index 00000000..2dbca0c4
--- /dev/null
+++ b/server/authentication/github.js
@@ -0,0 +1,32 @@
+'use strict'
+
+/* global wiki */
+
+// ------------------------------------
+// GitHub Account
+// ------------------------------------
+
+const GitHubStrategy = require('passport-github2').Strategy
+
+module.exports = {
+  key: 'github',
+  title: 'GitHub',
+  useForm: false,
+  props: ['clientId', 'clientSecret', 'callbackURL'],
+  init (passport, conf) {
+    passport.use('github',
+      new GitHubStrategy({
+        clientID: conf.clientId,
+        clientSecret: conf.clientSecret,
+        callbackURL: conf.callbackURL,
+        scope: ['user:email']
+      }, (accessToken, refreshToken, profile, cb) => {
+        wiki.db.User.processProfile(profile).then((user) => {
+          return cb(null, user) || true
+        }).catch((err) => {
+          return cb(err, null) || true
+        })
+      }
+      ))
+  }
+}
diff --git a/server/authentication/google.js b/server/authentication/google.js
new file mode 100644
index 00000000..d353e6c4
--- /dev/null
+++ b/server/authentication/google.js
@@ -0,0 +1,31 @@
+'use strict'
+
+/* global wiki */
+
+// ------------------------------------
+// Google ID Account
+// ------------------------------------
+
+const GoogleStrategy = require('passport-google-oauth20').Strategy
+
+module.exports = {
+  key: 'google',
+  title: 'Google ID',
+  useForm: false,
+  props: ['clientId', 'clientSecret', 'callbackURL'],
+  init (passport, conf) {
+    passport.use('google',
+      new GoogleStrategy({
+        clientID: conf.clientId,
+        clientSecret: conf.clientSecret,
+        callbackURL: conf.callbackURL
+      }, (accessToken, refreshToken, profile, cb) => {
+        wiki.db.User.processProfile(profile).then((user) => {
+          return cb(null, user) || true
+        }).catch((err) => {
+          return cb(err, null) || true
+        })
+      }
+      ))
+  }
+}
diff --git a/server/authentication/ldap.js b/server/authentication/ldap.js
new file mode 100644
index 00000000..720b5f4b
--- /dev/null
+++ b/server/authentication/ldap.js
@@ -0,0 +1,46 @@
+'use strict'
+
+/* global wiki */
+
+// ------------------------------------
+// LDAP Account
+// ------------------------------------
+
+const LdapStrategy = require('passport-ldapauth').Strategy
+const fs = require('fs')
+
+module.exports = {
+  key: 'ldap',
+  title: 'LDAP / Active Directory',
+  useForm: true,
+  props: ['url', 'bindDn', 'bindCredentials', 'searchBase', 'searchFilter', 'tlsEnabled', 'tlsCertPath'],
+  init (passport, conf) {
+    passport.use('ldapauth',
+      new LdapStrategy({
+        server: {
+          url: conf.url,
+          bindDn: conf.bindDn,
+          bindCredentials: conf.bindCredentials,
+          searchBase: conf.searchBase,
+          searchFilter: conf.searchFilter,
+          searchAttributes: ['displayName', 'name', 'cn', 'mail'],
+          tlsOptions: (conf.tlsEnabled) ? {
+            ca: [
+              fs.readFileSync(conf.tlsCertPath)
+            ]
+          } : {}
+        },
+        usernameField: 'email',
+        passReqToCallback: false
+      }, (profile, cb) => {
+        profile.provider = 'ldap'
+        profile.id = profile.dn
+        wiki.db.User.processProfile(profile).then((user) => {
+          return cb(null, user) || true
+        }).catch((err) => {
+          return cb(err, null) || true
+        })
+      }
+      ))
+  }
+}
diff --git a/server/authentication/local.js b/server/authentication/local.js
new file mode 100644
index 00000000..e2ca7faa
--- /dev/null
+++ b/server/authentication/local.js
@@ -0,0 +1,38 @@
+'use strict'
+
+/* global wiki */
+
+// ------------------------------------
+// Local Account
+// ------------------------------------
+
+const LocalStrategy = require('passport-local').Strategy
+
+module.exports = {
+  key: 'local',
+  title: 'Local',
+  useForm: true,
+  props: [],
+  init (passport, conf) {
+    passport.use('local',
+      new LocalStrategy({
+        usernameField: 'email',
+        passwordField: 'password'
+      }, (uEmail, uPassword, done) => {
+        wiki.db.User.findOne({ email: uEmail, provider: 'local' }).then((user) => {
+          if (user) {
+            return user.validatePassword(uPassword).then(() => {
+              return done(null, user) || true
+            }).catch((err) => {
+              return done(err, null)
+            })
+          } else {
+            return done(new Error('INVALID_LOGIN'), null)
+          }
+        }).catch((err) => {
+          done(err, null)
+        })
+      }
+      ))
+  }
+}
diff --git a/server/authentication/microsoft.js b/server/authentication/microsoft.js
new file mode 100644
index 00000000..b761aa41
--- /dev/null
+++ b/server/authentication/microsoft.js
@@ -0,0 +1,31 @@
+'use strict'
+
+/* global wiki */
+
+// ------------------------------------
+// Microsoft Account
+// ------------------------------------
+
+const WindowsLiveStrategy = require('passport-windowslive').Strategy
+
+module.exports = {
+  key: 'microsoft',
+  title: 'Microsoft Account',
+  useForm: false,
+  props: ['clientId', 'clientSecret', 'callbackURL'],
+  init (passport, conf) {
+    passport.use('microsoft',
+      new WindowsLiveStrategy({
+        clientID: conf.clientId,
+        clientSecret: conf.clientSecret,
+        callbackURL: conf.callbackURL
+      }, function (accessToken, refreshToken, profile, cb) {
+        wiki.db.User.processProfile(profile).then((user) => {
+          return cb(null, user) || true
+        }).catch((err) => {
+          return cb(err, null) || true
+        })
+      }
+      ))
+  }
+}
diff --git a/server/authentication/slack.js b/server/authentication/slack.js
new file mode 100644
index 00000000..e4aa6d5f
--- /dev/null
+++ b/server/authentication/slack.js
@@ -0,0 +1,31 @@
+'use strict'
+
+/* global wiki */
+
+// ------------------------------------
+// Slack Account
+// ------------------------------------
+
+const SlackStrategy = require('passport-slack').Strategy
+
+module.exports = {
+  key: 'slack',
+  title: 'Slack',
+  useForm: false,
+  props: ['clientId', 'clientSecret', 'callbackURL'],
+  init (passport, conf) {
+    passport.use('slack',
+      new SlackStrategy({
+        clientID: conf.clientId,
+        clientSecret: conf.clientSecret,
+        callbackURL: conf.callbackURL
+      }, (accessToken, refreshToken, profile, cb) => {
+        wiki.db.User.processProfile(profile).then((user) => {
+          return cb(null, user) || true
+        }).catch((err) => {
+          return cb(err, null) || true
+        })
+      }
+      ))
+  }
+}
diff --git a/server/configure.js b/server/configure.js
index 0766d695..78c00c3c 100644
--- a/server/configure.js
+++ b/server/configure.js
@@ -1,11 +1,12 @@
-'use strict'
+const path = require('path')
 
-module.exports = (port, spinner) => {
-  const path = require('path')
+/* global wiki */
 
-  const ROOTPATH = process.cwd()
-  const SERVERPATH = path.join(ROOTPATH, 'server')
-  const IS_DEBUG = process.env.NODE_ENV === 'development'
+module.exports = () => {
+  wiki.config.site = {
+    path: '',
+    title: 'Wiki.js'
+  }
 
   // ----------------------------------------
   // Load modules
@@ -26,28 +27,30 @@ module.exports = (port, spinner) => {
   // Define Express App
   // ----------------------------------------
 
-  var app = express()
+  let app = express()
   app.use(compression())
 
-  var server
+  let server
 
   // ----------------------------------------
   // Public Assets
   // ----------------------------------------
 
-  app.use(favicon(path.join(ROOTPATH, 'assets', 'favicon.ico')))
-  app.use(express.static(path.join(ROOTPATH, 'assets')))
+  app.use(favicon(path.join(wiki.ROOTPATH, 'assets', 'favicon.ico')))
+  app.use(express.static(path.join(wiki.ROOTPATH, 'assets')))
 
   // ----------------------------------------
   // View Engine Setup
   // ----------------------------------------
 
-  app.set('views', path.join(SERVERPATH, 'views'))
+  app.set('views', path.join(wiki.SERVERPATH, 'views'))
   app.set('view engine', 'pug')
 
   app.use(bodyParser.json())
   app.use(bodyParser.urlencoded({ extended: false }))
 
+  app.locals.config = wiki.config
+  app.locals.data = wiki.data
   app.locals._ = require('lodash')
 
   // ----------------------------------------
@@ -55,21 +58,8 @@ module.exports = (port, spinner) => {
   // ----------------------------------------
 
   app.get('*', (req, res) => {
-    let langs = []
-    let conf = {}
-    try {
-      langs = yaml.safeLoad(fs.readFileSync(path.join(SERVERPATH, 'app/data.yml'), 'utf8')).langs
-      conf = yaml.safeLoad(fs.readFileSync(path.join(ROOTPATH, 'config.yml'), 'utf8'))
-    } catch (err) {
-      console.error(err)
-    }
-    res.render('configure/index', {
-      langs,
-      conf,
-      runmode: {
-        staticPort: (process.env.WIKI_JS_HEROKU || process.env.WIKI_JS_DOCKER),
-        staticMongo: (!_.isNil(process.env.WIKI_JS_HEROKU))
-      }
+    fs.readJsonAsync(path.join(wiki.ROOTPATH, 'package.json')).then(packageObj => {
+      res.render('configure/index', { packageObj })
     })
   })
 
@@ -80,15 +70,15 @@ module.exports = (port, spinner) => {
     Promise.mapSeries([
       () => {
         const semver = require('semver')
-        if (!semver.satisfies(semver.clean(process.version), '>=6.9.0')) {
-          throw new Error('Node.js version is too old. Minimum is v6.6.0.')
+        if (!semver.satisfies(semver.clean(process.version), '>=6.11.1')) {
+          throw new Error('Node.js version is too old. Minimum is 6.11.1.')
         }
-        return 'Node.js ' + process.version + ' detected. Minimum is v6.9.0.'
+        return 'Node.js ' + process.version + ' detected. Minimum is 6.11.1.'
       },
       () => {
         return Promise.try(() => {
           require('crypto')
-        }).catch(err => { // eslint-disable-line handle-callback-err
+        }).catch(err => {
           throw new Error('Crypto Node.js module is not available.')
         }).return('Node.js Crypto module is available.')
       },
@@ -102,24 +92,24 @@ module.exports = (port, spinner) => {
             }
             let gitver = _.head(stdout.match(/[\d]+\.[\d]+(\.[\d]+)?/gi))
             if (!gitver || !semver.satisfies(semver.clean(gitver), '>=2.7.4')) {
-              reject(new Error('Git version is too old. Minimum is v2.7.4.'))
+              reject(new Error('Git version is too old. Minimum is 2.7.4.'))
             }
-            resolve('Git v' + gitver + ' detected. Minimum is v2.7.4.')
+            resolve('Git ' + gitver + ' detected. Minimum is 2.7.4.')
           })
         })
       },
       () => {
         const os = require('os')
-        if (os.totalmem() < 1000 * 1000 * 768) {
-          throw new Error('Not enough memory. Minimum is 768 MB.')
+        if (os.totalmem() < 1000 * 1000 * 512) {
+          throw new Error('Not enough memory. Minimum is 512 MB.')
         }
-        return _.round(os.totalmem() / (1024 * 1024)) + ' MB of system memory available. Minimum is 768 MB.'
+        return _.round(os.totalmem() / (1024 * 1024)) + ' MB of system memory available. Minimum is 512 MB.'
       },
       () => {
         let fs = require('fs')
         return Promise.try(() => {
-          fs.accessSync(path.join(ROOTPATH, 'config.yml'), (fs.constants || fs).W_OK)
-        }).catch(err => { // eslint-disable-line handle-callback-err
+          fs.accessSync(path.join(wiki.ROOTPATH, 'config.yml'), (fs.constants || fs).W_OK)
+        }).catch(err => {
           throw new Error('config.yml file is not writable by Node.js process or was not created properly.')
         }).return('config.yml is writable by the setup process.')
       }
@@ -130,43 +120,6 @@ module.exports = (port, spinner) => {
     })
   })
 
-  /**
-   * Check the DB connection
-   */
-  app.post('/dbcheck', (req, res) => {
-    let mongo = require('mongodb').MongoClient
-    let mongoURI = cfgHelper.parseConfigValue(req.body.db)
-    mongo.connect(mongoURI, {
-      autoReconnect: false,
-      reconnectTries: 2,
-      reconnectInterval: 1000,
-      connectTimeoutMS: 5000,
-      socketTimeoutMS: 5000
-    }, (err, db) => {
-      if (err === null) {
-        // Try to create a test collection
-        db.createCollection('test', (err, results) => {
-          if (err === null) {
-            // Try to drop test collection
-            db.dropCollection('test', (err, results) => {
-              if (err === null) {
-                res.json({ ok: true })
-              } else {
-                res.json({ ok: false, error: 'Unable to delete test collection. Verify permissions. ' + err.message })
-              }
-              db.close()
-            })
-          } else {
-            res.json({ ok: false, error: 'Unable to create test collection. Verify permissions. ' + err.message })
-            db.close()
-          }
-        })
-      } else {
-        res.json({ ok: false, error: err.message })
-      }
-    })
-  })
-
   /**
    * Check the Git connection
    */
@@ -174,8 +127,8 @@ module.exports = (port, spinner) => {
     const exec = require('execa')
     const url = require('url')
 
-    const dataDir = path.resolve(ROOTPATH, cfgHelper.parseConfigValue(req.body.pathData))
-    const gitDir = path.resolve(ROOTPATH, cfgHelper.parseConfigValue(req.body.pathRepo))
+    const dataDir = path.resolve(wiki.ROOTPATH, cfgHelper.parseConfigValue(req.body.pathData))
+    const gitDir = path.resolve(wiki.ROOTPATH, cfgHelper.parseConfigValue(req.body.pathRepo))
 
     let gitRemoteUrl = ''
 
@@ -315,7 +268,7 @@ module.exports = (port, spinner) => {
           }
         })
       }),
-      fs.readFileAsync(path.join(ROOTPATH, 'config.yml'), 'utf8').then(confRaw => {
+      fs.readFileAsync(path.join(wiki.ROOTPATH, 'config.yml'), 'utf8').then(confRaw => {
         let conf = yaml.safeLoad(confRaw)
         conf.title = req.body.title
         conf.host = req.body.host
@@ -356,12 +309,12 @@ module.exports = (port, spinner) => {
         return crypto.randomBytesAsync(32).then(buf => {
           conf.sessionSecret = buf.toString('hex')
           confRaw = yaml.safeDump(conf)
-          return fs.writeFileAsync(path.join(ROOTPATH, 'config.yml'), confRaw)
+          return fs.writeFileAsync(path.join(wiki.ROOTPATH, 'config.yml'), confRaw)
         })
       })
     ).then(() => {
       if (process.env.IS_HEROKU) {
-        return fs.outputJsonAsync(path.join(SERVERPATH, 'app/heroku.json'), { configured: true })
+        return fs.outputJsonAsync(path.join(wiki.SERVERPATH, 'app/heroku.json'), { configured: true })
       } else {
         return true
       }
@@ -377,7 +330,7 @@ module.exports = (port, spinner) => {
    */
   app.post('/restart', (req, res) => {
     res.status(204).end()
-    server.destroy(() => {
+    /* server.destroy(() => {
       spinner.text = 'Setup wizard terminated. Restarting in normal mode...'
       _.delay(() => {
         const exec = require('execa')
@@ -386,7 +339,7 @@ module.exports = (port, spinner) => {
           process.exit(0)
         })
       }, 1000)
-    })
+    }) */
   })
 
   // ----------------------------------------
@@ -403,21 +356,20 @@ module.exports = (port, spinner) => {
     res.status(err.status || 500)
     res.send({
       message: err.message,
-      error: IS_DEBUG ? err : {}
+      error: wiki.IS_DEBUG ? err : {}
     })
-    spinner.fail(err.message)
-    process.exit(1)
+    wiki.logger.error(err.message)
   })
 
   // ----------------------------------------
   // Start HTTP server
   // ----------------------------------------
 
-  spinner.text = 'Starting HTTP server...'
+  wiki.logger.info(`HTTP Server on port: ${wiki.config.port}`)
 
-  app.set('port', port)
+  app.set('port', wiki.config.port)
   server = http.createServer(app)
-  server.listen(port)
+  server.listen(wiki.config.port)
 
   var openConnections = []
 
@@ -443,10 +395,10 @@ module.exports = (port, spinner) => {
 
     switch (error.code) {
       case 'EACCES':
-        spinner.fail('Listening on port ' + port + ' requires elevated privileges!')
+        wiki.logger.error('Listening on port ' + wiki.config.port + ' requires elevated privileges!')
         return process.exit(1)
       case 'EADDRINUSE':
-        spinner.fail('Port ' + port + ' is already in use!')
+        wiki.logger.error('Port ' + wiki.config.port + ' is already in use!')
         return process.exit(1)
       default:
         throw error
@@ -454,6 +406,6 @@ module.exports = (port, spinner) => {
   })
 
   server.on('listening', () => {
-    spinner.text = 'Browse to http://localhost:' + port + ' to configure Wiki.js!'
+    wiki.logger.info('HTTP Server: RUNNING')
   })
 }
diff --git a/server/controllers/admin.js b/server/controllers/admin.js
index bc7554e0..962c6161 100644
--- a/server/controllers/admin.js
+++ b/server/controllers/admin.js
@@ -1,6 +1,6 @@
 'use strict'
 
-/* global db, lang, rights, winston */
+/* global wiki */
 
 var express = require('express')
 var router = express.Router()
@@ -33,14 +33,14 @@ router.post('/profile', (req, res) => {
     return res.render('error-forbidden')
   }
 
-  return db.User.findById(req.user.id).then((usr) => {
+  return wiki.db.User.findById(req.user.id).then((usr) => {
     usr.name = _.trim(req.body.name)
     if (usr.provider === 'local' && req.body.password !== '********') {
       let nPwd = _.trim(req.body.password)
       if (nPwd.length < 6) {
         return Promise.reject(new Error('New Password too short!'))
       } else {
-        return db.User.hashPassword(nPwd).then((pwd) => {
+        return wiki.db.User.hashPassword(nPwd).then((pwd) => {
           usr.password = pwd
           return usr.save()
         })
@@ -61,9 +61,9 @@ router.get('/stats', (req, res) => {
   }
 
   Promise.all([
-    db.Entry.count(),
-    db.UplFile.count(),
-    db.User.count()
+    wiki.db.Entry.count(),
+    wiki.db.UplFile.count(),
+    wiki.db.User.count()
   ]).spread((totalEntries, totalUploads, totalUsers) => {
     return res.render('pages/admin/stats', {
       totalEntries, totalUploads, totalUsers, adminTab: 'stats'
@@ -78,7 +78,7 @@ router.get('/users', (req, res) => {
     return res.render('error-forbidden')
   }
 
-  db.User.find({})
+  wiki.db.User.find({})
     .select('-password -rights')
     .sort('name email')
     .exec().then((usrs) => {
@@ -95,7 +95,7 @@ router.get('/users/:id', (req, res) => {
     return res.render('error-forbidden')
   }
 
-  db.User.findById(req.params.id)
+  wiki.db.User.findById(req.params.id)
     .select('-password -providerId')
     .exec().then((usr) => {
       let usrOpts = {
@@ -137,12 +137,12 @@ router.post('/users/create', (req, res) => {
     return res.status(400).json({ msg: 'Name is missing' })
   }
 
-  db.User.findOne({ email: nUsr.email, provider: nUsr.provider }).then(exUsr => {
+  wiki.db.User.findOne({ email: nUsr.email, provider: nUsr.provider }).then(exUsr => {
     if (exUsr) {
       return res.status(400).json({ msg: 'User already exists!' }) || true
     }
 
-    let pwdGen = (nUsr.provider === 'local') ? db.User.hashPassword(nUsr.password) : Promise.resolve(true)
+    let pwdGen = (nUsr.provider === 'local') ? wiki.db.User.hashPassword(nUsr.password) : Promise.resolve(true)
     return pwdGen.then(nPwd => {
       if (nUsr.provider !== 'local') {
         nUsr.password = ''
@@ -158,37 +158,37 @@ router.post('/users/create', (req, res) => {
         deny: false
       }]
 
-      return db.User.create(nUsr).then(() => {
+      return wiki.db.User.create(nUsr).then(() => {
         return res.json({ ok: true })
       })
     }).catch(err => {
-      winston.warn(err)
+      wiki.logger.warn(err)
       return res.status(500).json({ msg: err })
     })
   }).catch(err => {
-    winston.warn(err)
+    wiki.logger.warn(err)
     return res.status(500).json({ msg: err })
   })
 })
 
 router.post('/users/:id', (req, res) => {
   if (!res.locals.rights.manage) {
-    return res.status(401).json({ msg: lang.t('errors:unauthorized') })
+    return res.status(401).json({ msg: wiki.lang.t('errors:unauthorized') })
   }
 
   if (!validator.isMongoId(req.params.id)) {
-    return res.status(400).json({ msg: lang.t('errors:invaliduserid') })
+    return res.status(400).json({ msg: wiki.lang.t('errors:invaliduserid') })
   }
 
-  return db.User.findById(req.params.id).then((usr) => {
+  return wiki.db.User.findById(req.params.id).then((usr) => {
     usr.name = _.trim(req.body.name)
     usr.rights = JSON.parse(req.body.rights)
     if (usr.provider === 'local' && req.body.password !== '********') {
       let nPwd = _.trim(req.body.password)
       if (nPwd.length < 6) {
-        return Promise.reject(new Error(lang.t('errors:newpasswordtooshort')))
+        return Promise.reject(new Error(wiki.lang.t('errors:newpasswordtooshort')))
       } else {
-        return db.User.hashPassword(nPwd).then((pwd) => {
+        return wiki.db.User.hashPassword(nPwd).then((pwd) => {
           usr.password = pwd
           return usr.save()
         })
@@ -199,7 +199,7 @@ router.post('/users/:id', (req, res) => {
   }).then((usr) => {
     // Update guest rights for future requests
     if (usr.provider === 'local' && usr.email === 'guest') {
-      rights.guest = usr
+      wiki.rights.guest = usr
     }
     return usr
   }).then(() => {
@@ -214,14 +214,14 @@ router.post('/users/:id', (req, res) => {
  */
 router.delete('/users/:id', (req, res) => {
   if (!res.locals.rights.manage) {
-    return res.status(401).json({ msg: lang.t('errors:unauthorized') })
+    return res.status(401).json({ msg: wiki.lang.t('errors:unauthorized') })
   }
 
   if (!validator.isMongoId(req.params.id)) {
-    return res.status(400).json({ msg: lang.t('errors:invaliduserid') })
+    return res.status(400).json({ msg: wiki.lang.t('errors:invaliduserid') })
   }
 
-  return db.User.findByIdAndRemove(req.params.id).then(() => {
+  return wiki.db.User.findByIdAndRemove(req.params.id).then(() => {
     return res.json({ ok: true })
   }).catch((err) => {
     res.status(500).json({ ok: false, msg: err.message })
@@ -249,7 +249,7 @@ router.get('/system', (req, res) => {
     cwd: process.cwd()
   }
 
-  fs.readJsonAsync(path.join(ROOTPATH, 'package.json')).then(packageObj => {
+  fs.readJsonAsync(path.join(wiki.ROOTPATH, 'package.json')).then(packageObj => {
     axios.get('https://api.github.com/repos/Requarks/wiki/releases/latest').then(resp => {
       let sysversion = {
         current: 'v' + packageObj.version,
@@ -259,7 +259,7 @@ router.get('/system', (req, res) => {
 
       res.render('pages/admin/system', { adminTab: 'system', hostInfo, sysversion })
     }).catch(err => {
-      winston.warn(err)
+      wiki.logger.warn(err)
       res.render('pages/admin/system', { adminTab: 'system', hostInfo, sysversion: { current: 'v' + packageObj.version } })
     })
   })
@@ -287,19 +287,19 @@ router.post('/theme', (req, res) => {
     return res.render('error-forbidden')
   }
 
-  if (!validator.isIn(req.body.primary, appdata.colors)) {
+  if (!validator.isIn(req.body.primary, wiki.data.colors)) {
     return res.status(406).json({ msg: 'Primary color is invalid.' })
-  } else if (!validator.isIn(req.body.alt, appdata.colors)) {
+  } else if (!validator.isIn(req.body.alt, wiki.data.colors)) {
     return res.status(406).json({ msg: 'Alternate color is invalid.' })
-  } else if (!validator.isIn(req.body.footer, appdata.colors)) {
+  } else if (!validator.isIn(req.body.footer, wiki.data.colors)) {
     return res.status(406).json({ msg: 'Footer color is invalid.' })
   }
 
-  appconfig.theme.primary = req.body.primary
-  appconfig.theme.alt = req.body.alt
-  appconfig.theme.footer = req.body.footer
-  appconfig.theme.code.dark = req.body.codedark === 'true'
-  appconfig.theme.code.colorize = req.body.codecolorize === 'true'
+  wiki.config.theme.primary = req.body.primary
+  wiki.config.theme.alt = req.body.alt
+  wiki.config.theme.footer = req.body.footer
+  wiki.config.theme.code.dark = req.body.codedark === 'true'
+  wiki.config.theme.code.colorize = req.body.codecolorize === 'true'
 
   return res.json({ msg: 'OK' })
 })
diff --git a/server/controllers/auth.js b/server/controllers/auth.js
index b513470e..9188102a 100644
--- a/server/controllers/auth.js
+++ b/server/controllers/auth.js
@@ -1,19 +1,19 @@
-'use strict'
-
-/* global db, lang */
+/* global wiki */
 
 const Promise = require('bluebird')
 const express = require('express')
 const router = express.Router()
-const passport = require('passport')
 const ExpressBrute = require('express-brute')
-const ExpressBruteMongooseStore = require('express-brute-mongoose')
+const ExpressBruteRedisStore = require('express-brute-redis')
 const moment = require('moment')
+const _ = require('lodash')
 
 /**
  * Setup Express-Brute
  */
-const EBstore = new ExpressBruteMongooseStore(db.Bruteforce)
+const EBstore = new ExpressBruteRedisStore({
+  client: wiki.redis
+})
 const bruteforce = new ExpressBrute(EBstore, {
   freeRetries: 5,
   minWait: 60 * 1000,
@@ -22,8 +22,8 @@ const bruteforce = new ExpressBrute(EBstore, {
   failCallback (req, res, next, nextValidRequestDate) {
     req.flash('alert', {
       class: 'error',
-      title: lang.t('auth:errors.toomanyattempts'),
-      message: lang.t('auth:errors.toomanyattemptsmsg', { time: moment(nextValidRequestDate).fromNow() }),
+      title: wiki.lang.t('auth:errors.toomanyattempts'),
+      message: wiki.lang.t('auth:errors.toomanyattemptsmsg', { time: moment(nextValidRequestDate).fromNow() }),
       iconClass: 'fa-times'
     })
     res.redirect('/login')
@@ -35,23 +35,24 @@ const bruteforce = new ExpressBrute(EBstore, {
  */
 router.get('/login', function (req, res, next) {
   res.render('auth/login', {
-    usr: res.locals.usr
+    authStrategies: _.reject(wiki.auth.strategies, { key: 'local' }),
+    hasMultipleStrategies: Object.keys(wiki.config.auth.strategies).length > 1
   })
 })
 
 router.post('/login', bruteforce.prevent, function (req, res, next) {
   new Promise((resolve, reject) => {
     // [1] LOCAL AUTHENTICATION
-    passport.authenticate('local', function (err, user, info) {
+    wiki.auth.passport.authenticate('local', function (err, user, info) {
       if (err) { return reject(err) }
       if (!user) { return reject(new Error('INVALID_LOGIN')) }
       resolve(user)
     })(req, res, next)
   }).catch({ message: 'INVALID_LOGIN' }, err => {
-    if (appconfig.auth.ldap && appconfig.auth.ldap.enabled) {
+    if (_.has(wiki.config.auth.strategy, 'ldap')) {
       // [2] LDAP AUTHENTICATION
       return new Promise((resolve, reject) => {
-        passport.authenticate('ldapauth', function (err, user, info) {
+        wiki.auth.passport.authenticate('ldapauth', function (err, user, info) {
           if (err) { return reject(err) }
           if (info && info.message) { return reject(new Error(info.message)) }
           if (!user) { return reject(new Error('INVALID_LOGIN')) }
@@ -73,13 +74,13 @@ router.post('/login', bruteforce.prevent, function (req, res, next) {
     // LOGIN FAIL
     if (err.message === 'INVALID_LOGIN') {
       req.flash('alert', {
-        title: lang.t('auth:errors.invalidlogin'),
-        message: lang.t('auth:errors.invalidloginmsg')
+        title: wiki.lang.t('auth:errors.invalidlogin'),
+        message: wiki.lang.t('auth:errors.invalidloginmsg')
       })
       return res.redirect('/login')
     } else {
       req.flash('alert', {
-        title: lang.t('auth:errors.loginerror'),
+        title: wiki.lang.t('auth:errors.loginerror'),
         message: err.message
       })
       return res.redirect('/login')
@@ -91,19 +92,19 @@ router.post('/login', bruteforce.prevent, function (req, res, next) {
  * Social Login
  */
 
-router.get('/login/ms', passport.authenticate('windowslive', { scope: ['wl.signin', 'wl.basic', 'wl.emails'] }))
-router.get('/login/google', passport.authenticate('google', { scope: ['profile', 'email'] }))
-router.get('/login/facebook', passport.authenticate('facebook', { scope: ['public_profile', 'email'] }))
-router.get('/login/github', passport.authenticate('github', { scope: ['user:email'] }))
-router.get('/login/slack', passport.authenticate('slack', { scope: ['identity.basic', 'identity.email'] }))
-router.get('/login/azure', passport.authenticate('azure_ad_oauth2'))
+router.get('/login/ms', wiki.auth.passport.authenticate('windowslive', { scope: ['wl.signin', 'wl.basic', 'wl.emails'] }))
+router.get('/login/google', wiki.auth.passport.authenticate('google', { scope: ['profile', 'email'] }))
+router.get('/login/facebook', wiki.auth.passport.authenticate('facebook', { scope: ['public_profile', 'email'] }))
+router.get('/login/github', wiki.auth.passport.authenticate('github', { scope: ['user:email'] }))
+router.get('/login/slack', wiki.auth.passport.authenticate('slack', { scope: ['identity.basic', 'identity.email'] }))
+router.get('/login/azure', wiki.auth.passport.authenticate('azure_ad_oauth2'))
 
-router.get('/login/ms/callback', passport.authenticate('windowslive', { failureRedirect: '/login', successRedirect: '/' }))
-router.get('/login/google/callback', passport.authenticate('google', { failureRedirect: '/login', successRedirect: '/' }))
-router.get('/login/facebook/callback', passport.authenticate('facebook', { failureRedirect: '/login', successRedirect: '/' }))
-router.get('/login/github/callback', passport.authenticate('github', { failureRedirect: '/login', successRedirect: '/' }))
-router.get('/login/slack/callback', passport.authenticate('slack', { failureRedirect: '/login', successRedirect: '/' }))
-router.get('/login/azure/callback', passport.authenticate('azure_ad_oauth2', { failureRedirect: '/login', successRedirect: '/' }))
+router.get('/login/ms/callback', wiki.auth.passport.authenticate('windowslive', { failureRedirect: '/login', successRedirect: '/' }))
+router.get('/login/google/callback', wiki.auth.passport.authenticate('google', { failureRedirect: '/login', successRedirect: '/' }))
+router.get('/login/facebook/callback', wiki.auth.passport.authenticate('facebook', { failureRedirect: '/login', successRedirect: '/' }))
+router.get('/login/github/callback', wiki.auth.passport.authenticate('github', { failureRedirect: '/login', successRedirect: '/' }))
+router.get('/login/slack/callback', wiki.auth.passport.authenticate('slack', { failureRedirect: '/login', successRedirect: '/' }))
+router.get('/login/azure/callback', wiki.auth.passport.authenticate('azure_ad_oauth2', { failureRedirect: '/login', successRedirect: '/' }))
 
 /**
  * Logout
diff --git a/server/controllers/uploads.js b/server/controllers/uploads.js
index a2a3f2f2..40b19e68 100644
--- a/server/controllers/uploads.js
+++ b/server/controllers/uploads.js
@@ -1,6 +1,9 @@
 'use strict'
 
-/* global git, lang, lcdata, upl */
+/* global wiki */
+
+module.exports = false
+return
 
 const express = require('express')
 const router = express.Router()
@@ -12,7 +15,7 @@ const fs = Promise.promisifyAll(require('fs-extra'))
 const path = require('path')
 const _ = require('lodash')
 
-const validPathRe = new RegExp('^([a-z0-9/-' + appdata.regex.cjk + appdata.regex.arabic + ']+\\.[a-z0-9]+)$')
+const validPathRe = new RegExp('^([a-z0-9/-' + wiki.data.regex.cjk + wiki.data.regex.arabic + ']+\\.[a-z0-9]+)$')
 const validPathThumbsRe = new RegExp('^([a-z0-9]+\\.png)$')
 
 // ==========================================
@@ -28,7 +31,7 @@ router.get('/t/*', (req, res, next) => {
   // todo: Authentication-based access
 
   res.sendFile(fileName, {
-    root: lcdata.getThumbsPath(),
+    root: wiki.disk.getThumbsPath(),
     dotfiles: 'deny'
   }, (err) => {
     if (err) {
@@ -37,12 +40,12 @@ router.get('/t/*', (req, res, next) => {
   })
 })
 
-router.post('/img', lcdata.uploadImgHandler, (req, res, next) => {
+router.post('/img', wiki.disk.uploadImgHandler, (req, res, next) => {
   let destFolder = _.chain(req.body.folder).trim().toLower().value()
 
-  upl.validateUploadsFolder(destFolder).then((destFolderPath) => {
+  wiki.upl.validateUploadsFolder(destFolder).then((destFolderPath) => {
     if (!destFolderPath) {
-      res.json({ ok: false, msg: lang.t('errors:invalidfolder') })
+      res.json({ ok: false, msg: wiki.lang.t('errors:invalidfolder') })
       return true
     }
 
@@ -50,7 +53,7 @@ router.post('/img', lcdata.uploadImgHandler, (req, res, next) => {
       let destFilename = ''
       let destFilePath = ''
 
-      return lcdata.validateUploadsFilename(f.originalname, destFolder, true).then((fname) => {
+      return wiki.disk.validateUploadsFilename(f.originalname, destFolder, true).then((fname) => {
         destFilename = fname
         destFilePath = path.resolve(destFolderPath, destFilename)
 
@@ -60,7 +63,7 @@ router.post('/img', lcdata.uploadImgHandler, (req, res, next) => {
 
         let mimeInfo = fileType(buf)
         if (!_.includes(['image/png', 'image/jpeg', 'image/gif', 'image/webp'], mimeInfo.mime)) {
-          return Promise.reject(new Error(lang.t('errors:invalidfiletype')))
+          return Promise.reject(new Error(wiki.lang.t('errors:invalidfiletype')))
         }
         return true
       }).then(() => {
@@ -94,12 +97,12 @@ router.post('/img', lcdata.uploadImgHandler, (req, res, next) => {
   })
 })
 
-router.post('/file', lcdata.uploadFileHandler, (req, res, next) => {
+router.post('/file', wiki.disk.uploadFileHandler, (req, res, next) => {
   let destFolder = _.chain(req.body.folder).trim().toLower().value()
 
-  upl.validateUploadsFolder(destFolder).then((destFolderPath) => {
+  wiki.upl.validateUploadsFolder(destFolder).then((destFolderPath) => {
     if (!destFolderPath) {
-      res.json({ ok: false, msg: lang.t('errors:invalidfolder') })
+      res.json({ ok: false, msg: wiki.lang.t('errors:invalidfolder') })
       return true
     }
 
@@ -107,7 +110,7 @@ router.post('/file', lcdata.uploadFileHandler, (req, res, next) => {
       let destFilename = ''
       let destFilePath = ''
 
-      return lcdata.validateUploadsFilename(f.originalname, destFolder, false).then((fname) => {
+      return wiki.disk.validateUploadsFilename(f.originalname, destFolder, false).then((fname) => {
         destFilename = fname
         destFilePath = path.resolve(destFolderPath, destFilename)
 
@@ -150,7 +153,7 @@ router.get('/*', (req, res, next) => {
   // todo: Authentication-based access
 
   res.sendFile(fileName, {
-    root: git.getRepoPath() + '/uploads/',
+    root: wiki.git.getRepoPath() + '/uploads/',
     dotfiles: 'deny'
   }, (err) => {
     if (err) {
diff --git a/server/index.js b/server/index.js
index 07cc3df8..e74f5c2b 100644
--- a/server/index.js
+++ b/server/index.js
@@ -1,276 +1,43 @@
-'use strict'
-
 // ===========================================
 // Wiki.js
-// 1.0.0
 // Licensed under AGPLv3
 // ===========================================
 
 const path = require('path')
-const ROOTPATH = process.cwd()
-const SERVERPATH = path.join(ROOTPATH, 'server')
+const cluster = require('cluster')
 
-global.ROOTPATH = ROOTPATH
-global.SERVERPATH = SERVERPATH
-const IS_DEBUG = process.env.NODE_ENV === 'development'
+let wiki = {
+  IS_DEBUG: process.env.NODE_ENV === 'development',
+  IS_MASTER: cluster.isMaster,
+  ROOTPATH: process.cwd(),
+  SERVERPATH: path.join(process.cwd(), 'server'),
+  configSvc: require('./modules/config'),
+  kernel: require('./modules/kernel')
+}
+global.wiki = wiki
 
 process.env.VIPS_WARNING = false
 
-// if (IS_DEBUG) {
+// if (wiki.IS_DEBUG) {
 //   require('@glimpse/glimpse').init()
 // }
 
-let appconf = require('./libs/config')()
-global.appconfig = appconf.config
-global.appdata = appconf.data
+wiki.configSvc.init()
 
 // ----------------------------------------
-// Load Winston
+// Init Logger
 // ----------------------------------------
 
-global.winston = require('./libs/logger')(IS_DEBUG, 'SERVER')
-global.winston.info('Wiki.js is initializing...')
+wiki.logger = require('./modules/logger').init()
 
 // ----------------------------------------
-// Load global modules
+// Init DB
 // ----------------------------------------
 
-global.lcdata = require('./libs/local').init()
-global.db = require('./libs/db').init()
-global.entries = require('./libs/entries').init()
-global.git = require('./libs/git').init(false)
-global.lang = require('i18next')
-global.mark = require('./libs/markdown')
-global.search = require('./libs/search').init()
-global.upl = require('./libs/uploads').init()
+wiki.db = require('./modules/db').init()
 
 // ----------------------------------------
-// Load modules
+// Start Kernel
 // ----------------------------------------
 
-const autoload = require('auto-load')
-const bodyParser = require('body-parser')
-const compression = require('compression')
-const cookieParser = require('cookie-parser')
-const express = require('express')
-const favicon = require('serve-favicon')
-const flash = require('connect-flash')
-const fork = require('child_process').fork
-const http = require('http')
-const i18nBackend = require('i18next-node-fs-backend')
-const passport = require('passport')
-const passportSocketIo = require('passport.socketio')
-const session = require('express-session')
-const SessionMongoStore = require('connect-mongo')(session)
-const graceful = require('node-graceful')
-const socketio = require('socket.io')
-
-var mw = autoload(path.join(SERVERPATH, '/middlewares'))
-var ctrl = autoload(path.join(SERVERPATH, '/controllers'))
-
-// ----------------------------------------
-// Define Express App
-// ----------------------------------------
-
-const app = express()
-global.app = app
-app.use(compression())
-
-// ----------------------------------------
-// Security
-// ----------------------------------------
-
-app.use(mw.security)
-
-// ----------------------------------------
-// Public Assets
-// ----------------------------------------
-
-app.use(favicon(path.join(ROOTPATH, 'assets', 'favicon.ico')))
-app.use(express.static(path.join(ROOTPATH, 'assets'), {
-  index: false,
-  maxAge: '7d'
-}))
-
-// ----------------------------------------
-// Passport Authentication
-// ----------------------------------------
-
-require('./libs/auth')(passport)
-global.rights = require('./libs/rights')
-global.rights.init()
-
-let sessionStore = new SessionMongoStore({
-  mongooseConnection: global.db.connection,
-  touchAfter: 15
-})
-
-app.use(cookieParser())
-app.use(session({
-  name: 'wikijs.sid',
-  store: sessionStore,
-  secret: appconfig.sessionSecret,
-  resave: false,
-  saveUninitialized: false
-}))
-app.use(flash())
-app.use(passport.initialize())
-app.use(passport.session())
-
-// ----------------------------------------
-// SEO
-// ----------------------------------------
-
-app.use(mw.seo)
-
-// ----------------------------------------
-// Localization Engine
-// ----------------------------------------
-
-global.lang
-  .use(i18nBackend)
-  .init({
-    load: 'languageOnly',
-    ns: ['common', 'admin', 'auth', 'errors', 'git'],
-    defaultNS: 'common',
-    saveMissing: false,
-    preload: [appconfig.lang],
-    lng: appconfig.lang,
-    fallbackLng: 'en',
-    backend: {
-      loadPath: path.join(SERVERPATH, 'locales/{{lng}}/{{ns}}.json')
-    }
-  })
-
-// ----------------------------------------
-// View Engine Setup
-// ----------------------------------------
-
-app.set('views', path.join(SERVERPATH, 'views'))
-app.set('view engine', 'pug')
-
-app.use(bodyParser.json({ limit: '1mb' }))
-app.use(bodyParser.urlencoded({ extended: false, limit: '1mb' }))
-
-// ----------------------------------------
-// View accessible data
-// ----------------------------------------
-
-app.locals._ = require('lodash')
-app.locals.t = global.lang.t.bind(global.lang)
-app.locals.moment = require('moment')
-app.locals.moment.locale(appconfig.lang)
-app.locals.appconfig = appconfig
-app.use(mw.flash)
-
-// ----------------------------------------
-// Controllers
-// ----------------------------------------
-
-app.use('/', ctrl.auth)
-
-app.use('/uploads', mw.auth, ctrl.uploads)
-app.use('/admin', mw.auth, ctrl.admin)
-app.use('/', mw.auth, ctrl.pages)
-
-// ----------------------------------------
-// Error handling
-// ----------------------------------------
-
-app.use(function (req, res, next) {
-  var err = new Error('Not Found')
-  err.status = 404
-  next(err)
-})
-
-app.use(function (err, req, res, next) {
-  res.status(err.status || 500)
-  res.render('error', {
-    message: err.message,
-    error: IS_DEBUG ? err : {}
-  })
-})
-
-// ----------------------------------------
-// Start HTTP server
-// ----------------------------------------
-
-global.winston.info('Starting HTTP/WS server on port ' + appconfig.port + '...')
-
-app.set('port', appconfig.port)
-var server = http.createServer(app)
-var io = socketio(server)
-
-server.listen(appconfig.port)
-server.on('error', (error) => {
-  if (error.syscall !== 'listen') {
-    throw error
-  }
-
-  // handle specific listen errors with friendly messages
-  switch (error.code) {
-    case 'EACCES':
-      global.winston.error('Listening on port ' + appconfig.port + ' requires elevated privileges!')
-      return process.exit(1)
-    case 'EADDRINUSE':
-      global.winston.error('Port ' + appconfig.port + ' is already in use!')
-      return process.exit(1)
-    default:
-      throw error
-  }
-})
-
-server.on('listening', () => {
-  global.winston.info('HTTP/WS server started successfully! [RUNNING]')
-})
-
-// ----------------------------------------
-// WebSocket
-// ----------------------------------------
-
-io.use(passportSocketIo.authorize({
-  key: 'wikijs.sid',
-  store: sessionStore,
-  secret: appconfig.sessionSecret,
-  cookieParser,
-  success: (data, accept) => {
-    accept()
-  },
-  fail: (data, message, error, accept) => {
-    accept()
-  }
-}))
-
-io.on('connection', ctrl.ws)
-
-// ----------------------------------------
-// Start child processes
-// ----------------------------------------
-
-let bgAgent = fork(path.join(SERVERPATH, 'agent.js'))
-
-bgAgent.on('message', m => {
-  if (!m.action) {
-    return
-  }
-
-  switch (m.action) {
-    case 'searchAdd':
-      global.search.add(m.content)
-      break
-  }
-})
-
-// ----------------------------------------
-// Graceful shutdown
-// ----------------------------------------
-
-graceful.on('exit', () => {
-  global.winston.info('- SHUTTING DOWN - Terminating Background Agent...')
-  bgAgent.kill()
-  global.winston.info('- SHUTTING DOWN - Performing git sync...')
-  return global.git.resync().then(() => {
-    global.winston.info('- SHUTTING DOWN - Git sync successful. Now safe to exit.')
-    process.exit()
-  })
-})
+wiki.kernel.init()
diff --git a/server/init.js b/server/init.js
deleted file mode 100644
index 95b3ed52..00000000
--- a/server/init.js
+++ /dev/null
@@ -1,90 +0,0 @@
-'use strict'
-
-const Promise = require('bluebird')
-const fs = Promise.promisifyAll(require('fs-extra'))
-const pm2 = Promise.promisifyAll(require('pm2'))
-const ora = require('ora')
-const path = require('path')
-
-const ROOTPATH = process.cwd()
-
-module.exports = {
-  /**
-   * Detect the most appropriate start mode
-   */
-  startDetect: function () {
-    if (process.env.WIKI_JS_HEROKU) {
-      return this.startInHerokuMode()
-    } else {
-      return this.startInBackgroundMode()
-    }
-  },
-  /**
-   * Start in background mode
-   */
-  startInBackgroundMode: function () {
-    let spinner = ora('Initializing...').start()
-    return fs.emptyDirAsync(path.join(ROOTPATH, './logs')).then(() => {
-      return pm2.connectAsync().then(() => {
-        return pm2.startAsync({
-          name: 'wiki',
-          script: 'server',
-          cwd: ROOTPATH,
-          output: path.join(ROOTPATH, './logs/wiki-output.log'),
-          error: path.join(ROOTPATH, './logs/wiki-error.log'),
-          minUptime: 5000,
-          maxRestarts: 5
-        }).then(() => {
-          spinner.succeed('Wiki.js has started successfully.')
-        }).finally(() => {
-          pm2.disconnect()
-        })
-      })
-    }).catch(err => {
-      spinner.fail(err)
-      process.exit(1)
-    })
-  },
-  /**
-   * Start in Heroku mode
-   */
-  startInHerokuMode: function () {
-    console.warn('Incorrect command on Heroku, use instead: node server')
-    process.exit(1)
-  },
-  /**
-   * Stop Wiki.js process(es)
-   */
-  stop () {
-    let spinner = ora('Shutting down Wiki.js...').start()
-    return pm2.connectAsync().then(() => {
-      return pm2.stopAsync('wiki').then(() => {
-        spinner.succeed('Wiki.js has stopped successfully.')
-      }).finally(() => {
-        pm2.disconnect()
-      })
-    }).catch(err => {
-      spinner.fail(err)
-      process.exit(1)
-    })
-  },
-  /**
-   * Restart Wiki.js process(es)
-   */
-  restart: function () {
-    let self = this
-    return self.stop().delay(1000).then(() => {
-      self.startDetect()
-    })
-  },
-  /**
-   * Start the web-based configuration wizard
-   *
-   * @param {Number} port Port to bind the HTTP server on
-   */
-  configure (port) {
-    port = port || 3000
-    let spinner = ora('Initializing interactive setup...').start()
-    require('./configure')(port, spinner)
-  }
-}
diff --git a/server/libs/auth.js b/server/libs/auth.js
deleted file mode 100644
index 34271ccc..00000000
--- a/server/libs/auth.js
+++ /dev/null
@@ -1,261 +0,0 @@
-'use strict'
-
-/* global appconfig, appdata, db, lang, winston */
-
-const fs = require('fs')
-
-module.exports = function (passport) {
-  // Serialization user methods
-
-  passport.serializeUser(function (user, done) {
-    done(null, user._id)
-  })
-
-  passport.deserializeUser(function (id, done) {
-    db.User.findById(id).then((user) => {
-      if (user) {
-        done(null, user)
-      } else {
-        done(new Error(lang.t('auth:errors:usernotfound')), null)
-      }
-      return true
-    }).catch((err) => {
-      done(err, null)
-    })
-  })
-
-  // Local Account
-
-  if (appconfig.auth.local && appconfig.auth.local.enabled) {
-    const LocalStrategy = require('passport-local').Strategy
-    passport.use('local',
-      new LocalStrategy({
-        usernameField: 'email',
-        passwordField: 'password'
-      }, (uEmail, uPassword, done) => {
-        db.User.findOne({ email: uEmail, provider: 'local' }).then((user) => {
-          if (user) {
-            return user.validatePassword(uPassword).then(() => {
-              return done(null, user) || true
-            }).catch((err) => {
-              return done(err, null)
-            })
-          } else {
-            return done(new Error('INVALID_LOGIN'), null)
-          }
-        }).catch((err) => {
-          done(err, null)
-        })
-      }
-      ))
-  }
-
-  // Google ID
-
-  if (appconfig.auth.google && appconfig.auth.google.enabled) {
-    const GoogleStrategy = require('passport-google-oauth20').Strategy
-    passport.use('google',
-      new GoogleStrategy({
-        clientID: appconfig.auth.google.clientId,
-        clientSecret: appconfig.auth.google.clientSecret,
-        callbackURL: appconfig.host + '/login/google/callback'
-      }, (accessToken, refreshToken, profile, cb) => {
-        db.User.processProfile(profile).then((user) => {
-          return cb(null, user) || true
-        }).catch((err) => {
-          return cb(err, null) || true
-        })
-      }
-      ))
-  }
-
-  // Microsoft Accounts
-
-  if (appconfig.auth.microsoft && appconfig.auth.microsoft.enabled) {
-    const WindowsLiveStrategy = require('passport-windowslive').Strategy
-    passport.use('windowslive',
-      new WindowsLiveStrategy({
-        clientID: appconfig.auth.microsoft.clientId,
-        clientSecret: appconfig.auth.microsoft.clientSecret,
-        callbackURL: appconfig.host + '/login/ms/callback'
-      }, function (accessToken, refreshToken, profile, cb) {
-        db.User.processProfile(profile).then((user) => {
-          return cb(null, user) || true
-        }).catch((err) => {
-          return cb(err, null) || true
-        })
-      }
-      ))
-  }
-
-  // Facebook
-
-  if (appconfig.auth.facebook && appconfig.auth.facebook.enabled) {
-    const FacebookStrategy = require('passport-facebook').Strategy
-    passport.use('facebook',
-      new FacebookStrategy({
-        clientID: appconfig.auth.facebook.clientId,
-        clientSecret: appconfig.auth.facebook.clientSecret,
-        callbackURL: appconfig.host + '/login/facebook/callback',
-        profileFields: ['id', 'displayName', 'email']
-      }, function (accessToken, refreshToken, profile, cb) {
-        db.User.processProfile(profile).then((user) => {
-          return cb(null, user) || true
-        }).catch((err) => {
-          return cb(err, null) || true
-        })
-      }
-      ))
-  }
-
-  // GitHub
-
-  if (appconfig.auth.github && appconfig.auth.github.enabled) {
-    const GitHubStrategy = require('passport-github2').Strategy
-    passport.use('github',
-      new GitHubStrategy({
-        clientID: appconfig.auth.github.clientId,
-        clientSecret: appconfig.auth.github.clientSecret,
-        callbackURL: appconfig.host + '/login/github/callback',
-        scope: ['user:email']
-      }, (accessToken, refreshToken, profile, cb) => {
-        db.User.processProfile(profile).then((user) => {
-          return cb(null, user) || true
-        }).catch((err) => {
-          return cb(err, null) || true
-        })
-      }
-      ))
-  }
-
-  // Slack
-
-  if (appconfig.auth.slack && appconfig.auth.slack.enabled) {
-    const SlackStrategy = require('passport-slack').Strategy
-    passport.use('slack',
-      new SlackStrategy({
-        clientID: appconfig.auth.slack.clientId,
-        clientSecret: appconfig.auth.slack.clientSecret,
-        callbackURL: appconfig.host + '/login/slack/callback'
-      }, (accessToken, refreshToken, profile, cb) => {
-        db.User.processProfile(profile).then((user) => {
-          return cb(null, user) || true
-        }).catch((err) => {
-          return cb(err, null) || true
-        })
-      }
-      ))
-  }
-
-  // LDAP
-
-  if (appconfig.auth.ldap && appconfig.auth.ldap.enabled) {
-    const LdapStrategy = require('passport-ldapauth').Strategy
-    passport.use('ldapauth',
-      new LdapStrategy({
-        server: {
-          url: appconfig.auth.ldap.url,
-          bindDn: appconfig.auth.ldap.bindDn,
-          bindCredentials: appconfig.auth.ldap.bindCredentials,
-          searchBase: appconfig.auth.ldap.searchBase,
-          searchFilter: appconfig.auth.ldap.searchFilter,
-          searchAttributes: ['displayName', 'name', 'cn', 'mail'],
-          tlsOptions: (appconfig.auth.ldap.tlsEnabled) ? {
-            ca: [
-              fs.readFileSync(appconfig.auth.ldap.tlsCertPath)
-            ]
-          } : {}
-        },
-        usernameField: 'email',
-        passReqToCallback: false
-      }, (profile, cb) => {
-        profile.provider = 'ldap'
-        profile.id = profile.dn
-        db.User.processProfile(profile).then((user) => {
-          return cb(null, user) || true
-        }).catch((err) => {
-          return cb(err, null) || true
-        })
-      }
-      ))
-  }
-
-  // AZURE AD
-
-  if (appconfig.auth.azure && appconfig.auth.azure.enabled) {
-    const AzureAdOAuth2Strategy = require('passport-azure-ad-oauth2').Strategy
-    const jwt = require('jsonwebtoken')
-    passport.use('azure_ad_oauth2',
-      new AzureAdOAuth2Strategy({
-        clientID: appconfig.auth.azure.clientId,
-        clientSecret: appconfig.auth.azure.clientSecret,
-        callbackURL: appconfig.host + '/login/azure/callback',
-        resource: appconfig.auth.azure.resource,
-        tenant: appconfig.auth.azure.tenant
-      }, (accessToken, refreshToken, params, profile, cb) => {
-        let waadProfile = jwt.decode(params.id_token)
-        waadProfile.id = waadProfile.oid
-        waadProfile.provider = 'azure'
-        db.User.processProfile(waadProfile).then((user) => {
-          return cb(null, user) || true
-        }).catch((err) => {
-          return cb(err, null) || true
-        })
-      }
-      ))
-  }
-
-  // Create users for first-time
-
-  db.onReady.then(() => {
-    return db.User.findOne({ provider: 'local', email: 'guest' }).then((c) => {
-      if (c < 1) {
-        // Create guest account
-
-        return db.User.create({
-          provider: 'local',
-          email: 'guest',
-          name: 'Guest',
-          password: '',
-          rights: [{
-            role: 'read',
-            path: '/',
-            exact: false,
-            deny: !appconfig.public
-          }]
-        }).then(() => {
-          winston.info('[AUTH] Guest account created successfully!')
-        }).catch((err) => {
-          winston.error('[AUTH] An error occured while creating guest account:')
-          winston.error(err)
-        })
-      }
-    }).then(() => {
-      if (process.env.WIKI_JS_HEROKU) {
-        return db.User.findOne({ provider: 'local', email: process.env.WIKI_ADMIN_EMAIL }).then((c) => {
-          if (c < 1) {
-            // Create root admin account (HEROKU ONLY)
-
-            return db.User.create({
-              provider: 'local',
-              email: process.env.WIKI_ADMIN_EMAIL,
-              name: 'Administrator',
-              password: '$2a$04$MAHRw785Xe/Jd5kcKzr3D.VRZDeomFZu2lius4gGpZZ9cJw7B7Mna', // admin123 (default)
-              rights: [{
-                role: 'admin',
-                path: '/',
-                exact: false,
-                deny: false
-              }]
-            }).then(() => {
-              winston.info('[AUTH] Root admin account created successfully!')
-            }).catch((err) => {
-              winston.error('[AUTH] An error occured while creating root admin account:')
-              winston.error(err)
-            })
-          } else { return true }
-        })
-      } else { return true }
-    })
-  })
-}
diff --git a/server/libs/config.js b/server/libs/config.js
deleted file mode 100644
index 810af0d7..00000000
--- a/server/libs/config.js
+++ /dev/null
@@ -1,68 +0,0 @@
-'use strict'
-
-const fs = require('fs')
-const yaml = require('js-yaml')
-const _ = require('lodash')
-const path = require('path')
-const cfgHelper = require('../helpers/config')
-
-/**
- * Load Application Configuration
- *
- * @param      {Object}  confPaths  Path to the configuration files
- * @return     {Object}  Application Configuration
- */
-module.exports = (confPaths) => {
-  confPaths = _.defaults(confPaths, {
-    config: path.join(ROOTPATH, 'config.yml'),
-    data: path.join(SERVERPATH, 'app/data.yml'),
-    dataRegex: path.join(SERVERPATH, 'app/regex.js')
-  })
-
-  let appconfig = {}
-  let appdata = {}
-
-  try {
-    appconfig = yaml.safeLoad(
-      cfgHelper.parseConfigValue(
-        fs.readFileSync(confPaths.config, 'utf8')
-      )
-    )
-
-    appdata = yaml.safeLoad(fs.readFileSync(confPaths.data, 'utf8'))
-    appdata.regex = require(confPaths.dataRegex)
-  } catch (ex) {
-    console.error(ex)
-    process.exit(1)
-  }
-
-  // Merge with defaults
-
-  appconfig = _.defaultsDeep(appconfig, appdata.defaults.config)
-
-  // Check port
-
-  if (appconfig.port < 1) {
-    appconfig.port = process.env.PORT || 80
-  }
-
-  // Convert booleans
-
-  appconfig.public = (appconfig.public === true || _.toLower(appconfig.public) === 'true')
-
-  // List authentication strategies
-
-  appconfig.authStrategies = {
-    list: _.filter(appconfig.auth, ['enabled', true]),
-    socialEnabled: (_.chain(appconfig.auth).omit(['local', 'ldap']).filter(['enabled', true]).value().length > 0)
-  }
-  if (appconfig.authStrategies.list.length < 1) {
-    console.error(new Error('You must enable at least 1 authentication strategy!'))
-    process.exit(1)
-  }
-
-  return {
-    config: appconfig,
-    data: appdata
-  }
-}
diff --git a/server/libs/db.js b/server/libs/db.js
deleted file mode 100644
index 733d28a2..00000000
--- a/server/libs/db.js
+++ /dev/null
@@ -1,63 +0,0 @@
-'use strict'
-
-/* global ROOTPATH, appconfig, winston */
-
-const modb = require('mongoose')
-const fs = require('fs')
-const path = require('path')
-const _ = require('lodash')
-
-/**
- * MongoDB module
- *
- * @return     {Object}  MongoDB wrapper instance
- */
-module.exports = {
-
-  /**
-   * Initialize DB
-   *
-   * @return     {Object}  DB instance
-   */
-  init() {
-    let self = this
-
-    let dbModelsPath = path.join(SERVERPATH, 'models')
-
-    modb.Promise = require('bluebird')
-
-    // Event handlers
-
-    modb.connection.on('error', err => {
-      winston.error('Failed to connect to MongoDB instance.')
-      return err
-    })
-    modb.connection.once('open', function () {
-      winston.log('Connected to MongoDB instance.')
-    })
-
-    // Store connection handle
-
-    self.connection = modb.connection
-    self.ObjectId = modb.Types.ObjectId
-
-    // Load DB Models
-
-    fs
-      .readdirSync(dbModelsPath)
-      .filter(function (file) {
-        return (file.indexOf('.') !== 0)
-      })
-      .forEach(function (file) {
-        let modelName = _.upperFirst(_.camelCase(_.split(file, '.')[0]))
-        self[modelName] = require(path.join(dbModelsPath, file))
-      })
-
-    // Connect
-
-    self.onReady = modb.connect(appconfig.db, { useMongoClient: true })
-
-    return self
-  }
-
-}
diff --git a/server/libs/logger.js b/server/libs/logger.js
deleted file mode 100644
index 4a6f7884..00000000
--- a/server/libs/logger.js
+++ /dev/null
@@ -1,77 +0,0 @@
-'use strict'
-
-module.exports = (isDebug, processName) => {
-  let winston = require('winston')
-
-  if (typeof processName === 'undefined') {
-    processName = 'SERVER'
-  }
-
-  // Console
-
-  let logger = new (winston.Logger)({
-    level: (isDebug) ? 'debug' : 'info',
-    transports: [
-      new (winston.transports.Console)({
-        level: (isDebug) ? 'debug' : 'info',
-        prettyPrint: true,
-        colorize: true,
-        silent: false,
-        timestamp: true
-      })
-    ]
-  })
-
-  logger.filters.push((level, msg) => {
-    return '[' + processName + '] ' + msg
-  })
-
-  // External services
-
-  if (appconfig.externalLogging.bugsnag) {
-    const bugsnagTransport = require('./winston-transports/bugsnag')
-    logger.add(bugsnagTransport, {
-      level: 'warn',
-      key: appconfig.externalLogging.bugsnag
-    })
-  }
-
-  if (appconfig.externalLogging.loggly) {
-    require('winston-loggly-bulk')
-    logger.add(winston.transports.Loggly, {
-      token: appconfig.externalLogging.loggly.token,
-      subdomain: appconfig.externalLogging.loggly.subdomain,
-      tags: ['wiki-js'],
-      level: 'warn',
-      json: true
-    })
-  }
-
-  if (appconfig.externalLogging.papertrail) {
-    require('winston-papertrail').Papertrail // eslint-disable-line no-unused-expressions
-    logger.add(winston.transports.Papertrail, {
-      host: appconfig.externalLogging.papertrail.host,
-      port: appconfig.externalLogging.papertrail.port,
-      level: 'warn',
-      program: 'wiki.js'
-    })
-  }
-
-  if (appconfig.externalLogging.rollbar) {
-    const rollbarTransport = require('./winston-transports/rollbar')
-    logger.add(rollbarTransport, {
-      level: 'warn',
-      key: appconfig.externalLogging.rollbar
-    })
-  }
-
-  if (appconfig.externalLogging.sentry) {
-    const sentryTransport = require('./winston-transports/sentry')
-    logger.add(sentryTransport, {
-      level: 'warn',
-      key: appconfig.externalLogging.sentry
-    })
-  }
-
-  return logger
-}
diff --git a/server/libs/search-index/index.js b/server/libs/search-index/index.js
deleted file mode 100644
index 807219d9..00000000
--- a/server/libs/search-index/index.js
+++ /dev/null
@@ -1,81 +0,0 @@
-const bunyan = require('bunyan')
-const level = require('levelup')
-const down = require('memdown')
-const SearchIndexAdder = require('search-index-adder')
-const SearchIndexSearcher = require('search-index-searcher')
-
-module.exports = function (givenOptions, moduleReady) {
-  const optionsLoaded = function (err, SearchIndex) {
-    const siUtil = require('./siUtil.js')(SearchIndex.options)
-    if (err) return moduleReady(err)
-    SearchIndex.close = siUtil.close
-    SearchIndex.countDocs = siUtil.countDocs
-    getAdder(SearchIndex, adderLoaded)
-  }
-
-  const adderLoaded = function (err, SearchIndex) {
-    if (err) return moduleReady(err)
-    getSearcher(SearchIndex, searcherLoaded)
-  }
-
-  const searcherLoaded = function (err, SearchIndex) {
-    if (err) return moduleReady(err)
-    return moduleReady(err, SearchIndex)
-  }
-
-  getOptions(givenOptions, optionsLoaded)
-}
-
-const getAdder = function (SearchIndex, done) {
-  SearchIndexAdder(SearchIndex.options, function (err, searchIndexAdder) {
-    SearchIndex.add = searchIndexAdder.add
-    SearchIndex.callbackyAdd = searchIndexAdder.concurrentAdd // deprecated
-    SearchIndex.concurrentAdd = searchIndexAdder.concurrentAdd
-    SearchIndex.createWriteStream = searchIndexAdder.createWriteStream
-    SearchIndex.dbWriteStream = searchIndexAdder.dbWriteStream
-    SearchIndex.defaultPipeline = searchIndexAdder.defaultPipeline
-    SearchIndex.del = searchIndexAdder.deleter
-    SearchIndex.deleteStream = searchIndexAdder.deleteStream
-    SearchIndex.flush = searchIndexAdder.flush
-    done(err, SearchIndex)
-  })
-}
-
-const getSearcher = function (SearchIndex, done) {
-  SearchIndexSearcher(SearchIndex.options, function (err, searchIndexSearcher) {
-    SearchIndex.availableFields = searchIndexSearcher.availableFields
-    SearchIndex.buckets = searchIndexSearcher.bucketStream
-    SearchIndex.categorize = searchIndexSearcher.categoryStream
-    SearchIndex.dbReadStream = searchIndexSearcher.dbReadStream
-    SearchIndex.get = searchIndexSearcher.get
-    SearchIndex.match = searchIndexSearcher.match
-    SearchIndex.scan = searchIndexSearcher.scan
-    SearchIndex.search = searchIndexSearcher.search
-    SearchIndex.totalHits = searchIndexSearcher.totalHits
-    done(err, SearchIndex)
-  })
-}
-
-const getOptions = function (options, done) {
-  var SearchIndex = {}
-  SearchIndex.options = Object.assign({}, {
-    indexPath: 'si',
-    keySeparator: '○',
-    logLevel: 'error'
-  }, options)
-  options.log = bunyan.createLogger({
-    name: 'search-index',
-    level: options.logLevel
-  })
-  if (!options.indexes) {
-    level(SearchIndex.options.indexPath || 'si', {
-      valueEncoding: 'json',
-      db: down
-    }, function (err, db) {
-      SearchIndex.options.indexes = db
-      return done(err, SearchIndex)
-    })
-  } else {
-    return done(null, SearchIndex)
-  }
-}
diff --git a/server/libs/search-index/siUtil.js b/server/libs/search-index/siUtil.js
deleted file mode 100644
index bad264a7..00000000
--- a/server/libs/search-index/siUtil.js
+++ /dev/null
@@ -1,36 +0,0 @@
-'use strict'
-
-module.exports = function (siOptions) {
-  var siUtil = {}
-
-  siUtil.countDocs = function (callback) {
-    var count = 0
-    const gte = 'DOCUMENT' + siOptions.keySeparator
-    const lte = 'DOCUMENT' + siOptions.keySeparator + siOptions.keySeparator
-    siOptions.indexes.createReadStream({gte: gte, lte: lte})
-      .on('data', function (data) {
-        count++
-      })
-      .on('error', function (err) {
-        return callback(err, null)
-      })
-      .on('end', function () {
-        return callback(null, count)
-      })
-  }
-
-  siUtil.close = function (callback) {
-    siOptions.indexes.close(function (err) {
-      while (!siOptions.indexes.isClosed()) {
-        // log not always working here- investigate
-        if (siOptions.log) siOptions.log.info('closing...')
-      }
-      if (siOptions.indexes.isClosed()) {
-        if (siOptions.log) siOptions.log.info('closed...')
-        callback(err)
-      }
-    })
-  }
-
-  return siUtil
-}
diff --git a/server/locales/ja/auth.json b/server/locales/ja/auth.json
index eade4c28..e4218ead 100644
--- a/server/locales/ja/auth.json
+++ b/server/locales/ja/auth.json
@@ -13,7 +13,7 @@
     "invalidlogin": "不正なログイン",
     "invalidloginmsg": "Eメール又はパスワードが無効です。",
     "invaliduseremail": "無効なユーザーEメール",
-    "lognerror": "ログインエラー",
+    "loginerror": "ログインエラー",
     "notyetauthorized": "まだこのサイトにログインする権限がありません。",
     "toomanyattempts": "試行回数が多すぎます",
     "toomanyattemptsmsg": "短期間に失敗した試行回数が多すぎます。{{time}}にもう一度お試しください。",
diff --git a/server/master.js b/server/master.js
new file mode 100644
index 00000000..4d8a450c
--- /dev/null
+++ b/server/master.js
@@ -0,0 +1,186 @@
+/* global wiki */
+
+module.exports = () => {
+  // ----------------------------------------
+  // Load global modules
+  // ----------------------------------------
+
+  wiki.auth = require('./modules/auth').init()
+  wiki.disk = require('./modules/disk').init()
+  wiki.docs = require('./modules/documents').init()
+  wiki.git = require('./modules/git').init(false)
+  wiki.lang = require('./modules/localization').init()
+  wiki.mark = require('./modules/markdown')
+  wiki.search = require('./modules/search').init()
+  wiki.upl = require('./modules/uploads').init()
+
+  // ----------------------------------------
+  // Load modules
+  // ----------------------------------------
+
+  const autoload = require('auto-load')
+  const bodyParser = require('body-parser')
+  const compression = require('compression')
+  const cookieParser = require('cookie-parser')
+  const express = require('express')
+  const favicon = require('serve-favicon')
+  const flash = require('connect-flash')
+  const http = require('http')
+  const path = require('path')
+  const session = require('express-session')
+  const SessionRedisStore = require('connect-redis')(session)
+  const graceful = require('node-graceful')
+  const graphqlApollo = require('apollo-server-express')
+  const graphqlSchema = require('./modules/graphql')
+
+  var mw = autoload(path.join(wiki.SERVERPATH, '/middlewares'))
+  var ctrl = autoload(path.join(wiki.SERVERPATH, '/controllers'))
+
+  // ----------------------------------------
+  // Define Express App
+  // ----------------------------------------
+
+  const app = express()
+  wiki.app = app
+  app.use(compression())
+
+  // ----------------------------------------
+  // Security
+  // ----------------------------------------
+
+  app.use(mw.security)
+
+  // ----------------------------------------
+  // Public Assets
+  // ----------------------------------------
+
+  app.use(favicon(path.join(wiki.ROOTPATH, 'assets', 'favicon.ico')))
+  app.use(express.static(path.join(wiki.ROOTPATH, 'assets'), {
+    index: false,
+    maxAge: '7d'
+  }))
+
+  // ----------------------------------------
+  // Passport Authentication
+  // ----------------------------------------
+
+  let sessionStore = new SessionRedisStore({
+    client: wiki.redis
+  })
+
+  app.use(cookieParser())
+  app.use(session({
+    name: 'wikijs.sid',
+    store: sessionStore,
+    secret: wiki.config.site.sessionSecret,
+    resave: false,
+    saveUninitialized: false
+  }))
+  app.use(flash())
+  app.use(wiki.auth.passport.initialize())
+  app.use(wiki.auth.passport.session())
+
+  // ----------------------------------------
+  // SEO
+  // ----------------------------------------
+
+  app.use(mw.seo)
+
+  // ----------------------------------------
+  // View Engine Setup
+  // ----------------------------------------
+
+  app.set('views', path.join(wiki.SERVERPATH, 'views'))
+  app.set('view engine', 'pug')
+
+  app.use(bodyParser.json({ limit: '1mb' }))
+  app.use(bodyParser.urlencoded({ extended: false, limit: '1mb' }))
+
+  // ----------------------------------------
+  // View accessible data
+  // ----------------------------------------
+
+  app.locals.basedir = wiki.ROOTPATH
+  app.locals._ = require('lodash')
+  app.locals.t = wiki.lang.engine.t.bind(wiki.lang)
+  app.locals.moment = require('moment')
+  app.locals.moment.locale(wiki.config.site.lang)
+  app.locals.config = wiki.config
+  app.use(mw.flash)
+
+  // ----------------------------------------
+  // Controllers
+  // ----------------------------------------
+
+  app.use('/', ctrl.auth)
+
+  app.use('/graphql', graphqlApollo.graphqlExpress({ schema: graphqlSchema }))
+  app.use('/graphiql', graphqlApollo.graphiqlExpress({ endpointURL: '/graphql' }))
+  // app.use('/uploads', mw.auth, ctrl.uploads)
+  app.use('/admin', mw.auth, ctrl.admin)
+  app.use('/', mw.auth, ctrl.pages)
+
+  // ----------------------------------------
+  // Error handling
+  // ----------------------------------------
+
+  app.use(function (req, res, next) {
+    var err = new Error('Not Found')
+    err.status = 404
+    next(err)
+  })
+
+  app.use(function (err, req, res, next) {
+    res.status(err.status || 500)
+    res.render('error', {
+      message: err.message,
+      error: wiki.IS_DEBUG ? err : {}
+    })
+  })
+
+  // ----------------------------------------
+  // Start HTTP server
+  // ----------------------------------------
+
+  wiki.logger.info(`HTTP Server on port: ${wiki.config.port}`)
+
+  app.set('port', wiki.config.port)
+  let server = http.createServer(app)
+
+  server.listen(wiki.config.port)
+  server.on('error', (error) => {
+    if (error.syscall !== 'listen') {
+      throw error
+    }
+
+    // handle specific listen errors with friendly messages
+    switch (error.code) {
+      case 'EACCES':
+        wiki.logger.error('Listening on port ' + wiki.config.port + ' requires elevated privileges!')
+        return process.exit(1)
+      case 'EADDRINUSE':
+        wiki.logger.error('Port ' + wiki.config.port + ' is already in use!')
+        return process.exit(1)
+      default:
+        throw error
+    }
+  })
+
+  server.on('listening', () => {
+    wiki.logger.info('HTTP Server: RUNNING')
+  })
+
+  // ----------------------------------------
+  // Graceful shutdown
+  // ----------------------------------------
+
+  graceful.on('exit', () => {
+    wiki.logger.info('- SHUTTING DOWN - Performing git sync...')
+    return global.git.resync().then(() => {
+      wiki.logger.info('- SHUTTING DOWN - Git sync successful. Now safe to exit.')
+      process.exit()
+    })
+  })
+
+  return true
+}
diff --git a/server/middlewares/flash.js b/server/middlewares/flash.js
index 98182b47..09e4adf0 100644
--- a/server/middlewares/flash.js
+++ b/server/middlewares/flash.js
@@ -9,7 +9,7 @@
  * @return     {any}               void
  */
 module.exports = (req, res, next) => {
-  res.locals.appflash = req.flash('alert')
+  res.locals.flash = req.flash('alert')
 
   next()
 }
diff --git a/server/middlewares/security.js b/server/middlewares/security.js
index 3590cff4..0fe2b355 100644
--- a/server/middlewares/security.js
+++ b/server/middlewares/security.js
@@ -1,7 +1,5 @@
 'use strict'
 
-/* global app */
-
 /**
  * Security Middleware
  *
@@ -12,7 +10,7 @@
  */
 module.exports = function (req, res, next) {
   // -> Disable X-Powered-By
-  app.disable('x-powered-by')
+  req.app.disable('x-powered-by')
 
   // -> Disable Frame Embedding
   res.set('X-Frame-Options', 'deny')
diff --git a/server/models/_relations.js b/server/models/_relations.js
new file mode 100644
index 00000000..c826a5e0
--- /dev/null
+++ b/server/models/_relations.js
@@ -0,0 +1,16 @@
+/**
+ * Associate DB Model relations
+ */
+module.exports = db => {
+  db.User.belongsToMany(db.Group, { through: 'userGroups' })
+  db.Group.belongsToMany(db.User, { through: 'userGroups' })
+  db.Group.hasMany(db.Right)
+  db.Right.belongsTo(db.Group)
+  db.Document.belongsToMany(db.Tag, { through: 'documentTags' })
+  db.Document.hasMany(db.Comment)
+  db.Tag.belongsToMany(db.Document, { through: 'documentTags' })
+  db.File.belongsTo(db.Folder)
+  db.Folder.hasMany(db.File)
+  db.Comment.belongsTo(db.Document)
+  db.Comment.belongsTo(db.User, { as: 'author' })
+}
diff --git a/server/models/bruteforce.js b/server/models/bruteforce.js
deleted file mode 100644
index 76981fd7..00000000
--- a/server/models/bruteforce.js
+++ /dev/null
@@ -1,20 +0,0 @@
-'use strict'
-
-const Mongoose = require('mongoose')
-
-/**
- * BruteForce schema
- *
- * @type       {<Mongoose.Schema>}
- */
-var bruteForceSchema = Mongoose.Schema({
-  _id: { type: String, index: 1 },
-  data: {
-    count: Number,
-    lastRequest: Date,
-    firstRequest: Date
-  },
-  expires: { type: Date, index: { expires: '1d' } }
-})
-
-module.exports = Mongoose.model('Bruteforce', bruteForceSchema)
diff --git a/server/models/comment.js b/server/models/comment.js
new file mode 100644
index 00000000..3b35f42c
--- /dev/null
+++ b/server/models/comment.js
@@ -0,0 +1,16 @@
+/**
+ * Comment schema
+ */
+module.exports = (sequelize, DataTypes) => {
+  let commentSchema = sequelize.define('comment', {
+    content: {
+      type: DataTypes.STRING,
+      allowNull: false
+    }
+  }, {
+    timestamps: true,
+    version: true
+  })
+
+  return commentSchema
+}
diff --git a/server/models/document.js b/server/models/document.js
new file mode 100644
index 00000000..957fd91a
--- /dev/null
+++ b/server/models/document.js
@@ -0,0 +1,64 @@
+/**
+ * Document schema
+ */
+module.exports = (sequelize, DataTypes) => {
+  let documentSchema = sequelize.define('setting', {
+    path: {
+      type: DataTypes.STRING,
+      allowNull: false
+    },
+    title: {
+      type: DataTypes.STRING,
+      allowNull: false,
+      validate: {
+        len: [2, 255]
+      }
+    },
+    subtitle: {
+      type: DataTypes.STRING,
+      allowNull: true,
+      defaultValue: ''
+    },
+    parentPath: {
+      type: DataTypes.STRING,
+      allowNull: true,
+      defaultValue: ''
+    },
+    parentTitle: {
+      type: DataTypes.STRING,
+      allowNull: true,
+      defaultValue: ''
+    },
+    isDirectory: {
+      type: DataTypes.BOOLEAN,
+      allowNull: false,
+      defaultValue: false
+    },
+    isEntry: {
+      type: DataTypes.BOOLEAN,
+      allowNull: false,
+      defaultValue: false
+    },
+    isDraft: {
+      type: DataTypes.BOOLEAN,
+      allowNull: false,
+      defaultValue: false
+    },
+    searchContent: {
+      type: DataTypes.TEXT,
+      allowNull: true,
+      defaultValue: ''
+    }
+  }, {
+    timestamps: true,
+    version: true,
+    indexes: [
+      {
+        unique: true,
+        fields: ['path']
+      }
+    ]
+  })
+
+  return documentSchema
+}
diff --git a/server/models/entry.js b/server/models/entry.js
deleted file mode 100644
index 746d6d28..00000000
--- a/server/models/entry.js
+++ /dev/null
@@ -1,42 +0,0 @@
-'use strict'
-
-const Mongoose = require('mongoose')
-
-/**
- * Entry schema
- *
- * @type       {<Mongoose.Schema>}
- */
-var entrySchema = Mongoose.Schema({
-  _id: String,
-
-  title: {
-    type: String,
-    required: true,
-    minlength: 2
-  },
-  subtitle: {
-    type: String,
-    default: ''
-  },
-  parentTitle: {
-    type: String,
-    default: ''
-  },
-  parentPath: {
-    type: String,
-    default: ''
-  },
-  isDirectory: {
-    type: Boolean,
-    default: false
-  },
-  isEntry: {
-    type: Boolean,
-    default: false
-  }
-}, {
-  timestamps: {}
-})
-
-module.exports = Mongoose.model('Entry', entrySchema)
diff --git a/server/models/file.js b/server/models/file.js
new file mode 100644
index 00000000..9fca9df4
--- /dev/null
+++ b/server/models/file.js
@@ -0,0 +1,42 @@
+/**
+ * File schema
+ */
+module.exports = (sequelize, DataTypes) => {
+  let fileSchema = sequelize.define('file', {
+    category: {
+      type: DataTypes.ENUM('binary', 'image'),
+      allowNull: false,
+      defaultValue: 'binary'
+    },
+    mime: {
+      type: DataTypes.STRING,
+      allowNull: false,
+      defaultValue: 'application/octet-stream'
+    },
+    extra: {
+      type: DataTypes.JSONB,
+      allowNull: true
+    },
+    filename: {
+      type: DataTypes.STRING,
+      allowNull: false
+    },
+    basename: {
+      type: DataTypes.STRING,
+      allowNull: false
+    },
+    filesize: {
+      type: DataTypes.INTEGER,
+      allowNull: false,
+      validate: {
+        isInt: true,
+        min: 0
+      }
+    }
+  }, {
+    timestamps: true,
+    version: true
+  })
+
+  return fileSchema
+}
diff --git a/server/models/folder.js b/server/models/folder.js
new file mode 100644
index 00000000..fdab4f7d
--- /dev/null
+++ b/server/models/folder.js
@@ -0,0 +1,22 @@
+/**
+ * Folder schema
+ */
+module.exports = (sequelize, DataTypes) => {
+  let folderSchema = sequelize.define('folder', {
+    name: {
+      type: DataTypes.STRING,
+      allowNull: false
+    }
+  }, {
+    timestamps: true,
+    version: true,
+    indexes: [
+      {
+        unique: true,
+        fields: ['name']
+      }
+    ]
+  })
+
+  return folderSchema
+}
diff --git a/server/models/group.js b/server/models/group.js
new file mode 100644
index 00000000..942ed07e
--- /dev/null
+++ b/server/models/group.js
@@ -0,0 +1,16 @@
+/**
+ * Group schema
+ */
+module.exports = (sequelize, DataTypes) => {
+  let groupSchema = sequelize.define('group', {
+    name: {
+      type: DataTypes.STRING,
+      allowNull: false
+    }
+  }, {
+    timestamps: true,
+    version: true
+  })
+
+  return groupSchema
+}
diff --git a/server/models/right.js b/server/models/right.js
new file mode 100644
index 00000000..eeed3155
--- /dev/null
+++ b/server/models/right.js
@@ -0,0 +1,36 @@
+/**
+ * Right schema
+ */
+module.exports = (sequelize, DataTypes) => {
+  let rightSchema = sequelize.define('right', {
+    path: {
+      type: DataTypes.STRING,
+      allowNull: false
+    },
+    role: {
+      type: DataTypes.ENUM('read', 'write', 'manage'),
+      allowNull: false,
+      defaultValue: 'read'
+    },
+    exact: {
+      type: DataTypes.BOOLEAN,
+      allowNull: false,
+      defaultValue: false
+    },
+    allow: {
+      type: DataTypes.BOOLEAN,
+      allowNull: false,
+      defaultValue: false
+    }
+  }, {
+    timestamps: true,
+    version: true,
+    indexes: [
+      {
+        fields: ['path']
+      }
+    ]
+  })
+
+  return rightSchema
+}
diff --git a/server/models/setting.js b/server/models/setting.js
index 73686af2..9759b7c3 100644
--- a/server/models/setting.js
+++ b/server/models/setting.js
@@ -1,22 +1,26 @@
-'use strict'
-
-const Mongoose = require('mongoose')
-
 /**
  * Settings schema
- *
- * @type       {<Mongoose.Schema>}
  */
-var settingSchema = Mongoose.Schema({
-  key: {
-    type: String,
-    required: true,
-    index: true
-  },
-  value: {
-    type: String,
-    required: true
-  }
-}, { timestamps: {} })
+module.exports = (sequelize, DataTypes) => {
+  let settingSchema = sequelize.define('setting', {
+    key: {
+      type: DataTypes.STRING,
+      allowNull: false
+    },
+    config: {
+      type: DataTypes.JSONB,
+      allowNull: false
+    }
+  }, {
+    timestamps: true,
+    version: true,
+    indexes: [
+      {
+        unique: true,
+        fields: ['key']
+      }
+    ]
+  })
 
-module.exports = Mongoose.model('Setting', settingSchema)
+  return settingSchema
+}
diff --git a/server/models/tag.js b/server/models/tag.js
new file mode 100644
index 00000000..6c44859d
--- /dev/null
+++ b/server/models/tag.js
@@ -0,0 +1,22 @@
+/**
+ * Tags schema
+ */
+module.exports = (sequelize, DataTypes) => {
+  let tagSchema = sequelize.define('tag', {
+    key: {
+      type: DataTypes.STRING,
+      allowNull: false
+    }
+  }, {
+    timestamps: true,
+    version: true,
+    indexes: [
+      {
+        unique: true,
+        fields: ['key']
+      }
+    ]
+  })
+
+  return tagSchema
+}
diff --git a/server/models/upl-file.js b/server/models/upl-file.js
deleted file mode 100644
index a48602bb..00000000
--- a/server/models/upl-file.js
+++ /dev/null
@@ -1,46 +0,0 @@
-'use strict'
-
-const Mongoose = require('mongoose')
-
-/**
- * Upload File schema
- *
- * @type       {<Mongoose.Schema>}
- */
-var uplFileSchema = Mongoose.Schema({
-
-  _id: String,
-
-  category: {
-    type: String,
-    required: true,
-    default: 'binary'
-  },
-  mime: {
-    type: String,
-    required: true,
-    default: 'application/octet-stream'
-  },
-  extra: {
-    type: Object
-  },
-  folder: {
-    type: String,
-    ref: 'UplFolder'
-  },
-  filename: {
-    type: String,
-    required: true
-  },
-  basename: {
-    type: String,
-    required: true
-  },
-  filesize: {
-    type: Number,
-    required: true
-  }
-
-}, { timestamps: {} })
-
-module.exports = Mongoose.model('UplFile', uplFileSchema)
diff --git a/server/models/upl-folder.js b/server/models/upl-folder.js
deleted file mode 100644
index 80028b6f..00000000
--- a/server/models/upl-folder.js
+++ /dev/null
@@ -1,21 +0,0 @@
-'use strict'
-
-const Mongoose = require('mongoose')
-
-/**
- * Upload Folder schema
- *
- * @type       {<Mongoose.Schema>}
- */
-var uplFolderSchema = Mongoose.Schema({
-
-  _id: String,
-
-  name: {
-    type: String,
-    index: true
-  }
-
-}, { timestamps: {} })
-
-module.exports = Mongoose.model('UplFolder', uplFolderSchema)
diff --git a/server/models/user.js b/server/models/user.js
index 18b2e429..c9102ac7 100644
--- a/server/models/user.js
+++ b/server/models/user.js
@@ -1,109 +1,120 @@
-'use strict'
+/* global wiki */
 
-/* global db, lang */
-
-const Mongoose = require('mongoose')
 const Promise = require('bluebird')
 const bcrypt = require('bcryptjs-then')
 const _ = require('lodash')
 
 /**
  * Users schema
- *
- * @type       {<Mongoose.Schema>}
  */
-var userSchema = Mongoose.Schema({
+module.exports = (sequelize, DataTypes) => {
+  let userSchema = sequelize.define('user', {
+    email: {
+      type: DataTypes.STRING,
+      allowNull: false,
+      validate: {
+        isEmail: true
+      }
+    },
+    provider: {
+      type: DataTypes.STRING,
+      allowNull: false
+    },
+    providerId: {
+      type: DataTypes.STRING,
+      allowNull: true
+    },
+    password: {
+      type: DataTypes.STRING,
+      allowNull: true
+    },
+    name: {
+      type: DataTypes.STRING,
+      allowNull: true
+    },
+    role: {
+      type: DataTypes.ENUM('admin', 'user', 'guest'),
+      allowNull: false
+    },
+    tfaIsActive: {
+      type: DataTypes.BOOLEAN,
+      allowNull: false,
+      defaultValue: false
+    },
+    tfaSecret: {
+      type: DataTypes.STRING,
+      allowNull: true
+    }
+  }, {
+    timestamps: true,
+    version: true,
+    indexes: [
+      {
+        unique: true,
+        fields: ['provider', 'email']
+      }
+    ]
+  })
 
-  email: {
-    type: String,
-    required: true,
-    index: true
-  },
-
-  provider: {
-    type: String,
-    required: true
-  },
-
-  providerId: {
-    type: String
-  },
-
-  password: {
-    type: String
-  },
-
-  name: {
-    type: String
-  },
-
-  rights: [{
-    role: String,
-    path: String,
-    exact: Boolean,
-    deny: Boolean
-  }]
-
-}, { timestamps: {} })
-
-userSchema.statics.processProfile = (profile) => {
-  let primaryEmail = ''
-  if (_.isArray(profile.emails)) {
-    let e = _.find(profile.emails, ['primary', true])
-    primaryEmail = (e) ? e.value : _.first(profile.emails).value
-  } else if (_.isString(profile.email) && profile.email.length > 5) {
-    primaryEmail = profile.email
-  } else if (_.isString(profile.mail) && profile.mail.length > 5) {
-    primaryEmail = profile.mail
-  } else if (profile.user && profile.user.email && profile.user.email.length > 5) {
-    primaryEmail = profile.user.email
-  } else {
-    return Promise.reject(new Error(lang.t('auth:errors.invaliduseremail')))
+  userSchema.prototype.validatePassword = function (rawPwd) {
+    return bcrypt.compare(rawPwd, this.password).then((isValid) => {
+      return (isValid) ? true : Promise.reject(new Error(wiki.lang.t('auth:errors:invalidlogin')))
+    })
   }
 
-  profile.provider = _.lowerCase(profile.provider)
-  primaryEmail = _.toLower(primaryEmail)
-
-  return db.User.findOneAndUpdate({
-    email: primaryEmail,
-    provider: profile.provider
-  }, {
-    email: primaryEmail,
-    provider: profile.provider,
-    providerId: profile.id,
-    name: profile.displayName || profile.cn || _.split(primaryEmail, '@')[0]
-  }, {
-    new: true
-  }).then((user) => {
-    // Handle unregistered accounts
-    if (!user && profile.provider !== 'local' && (appconfig.auth.defaultReadAccess || profile.provider === 'ldap' || profile.provider === 'azure')) {
-      let nUsr = {
-        email: primaryEmail,
-        provider: profile.provider,
-        providerId: profile.id,
-        password: '',
-        name: profile.displayName || profile.name || profile.cn,
-        rights: [{
-          role: 'read',
-          path: '/',
-          exact: false,
-          deny: false
-        }]
-      }
-      return db.User.create(nUsr)
+  userSchema.processProfile = (profile) => {
+    let primaryEmail = ''
+    if (_.isArray(profile.emails)) {
+      let e = _.find(profile.emails, ['primary', true])
+      primaryEmail = (e) ? e.value : _.first(profile.emails).value
+    } else if (_.isString(profile.email) && profile.email.length > 5) {
+      primaryEmail = profile.email
+    } else if (_.isString(profile.mail) && profile.mail.length > 5) {
+      primaryEmail = profile.mail
+    } else if (profile.user && profile.user.email && profile.user.email.length > 5) {
+      primaryEmail = profile.user.email
+    } else {
+      return Promise.reject(new Error(wiki.lang.t('auth:errors.invaliduseremail')))
     }
-    return user || Promise.reject(new Error(lang.t('auth:errors:notyetauthorized')))
-  })
-}
 
-userSchema.statics.hashPassword = (rawPwd) => {
-  return bcrypt.hash(rawPwd)
-}
+    profile.provider = _.lowerCase(profile.provider)
+    primaryEmail = _.toLower(primaryEmail)
 
-userSchema.methods.validatePassword = function (rawPwd) {
-  return bcrypt.compare(rawPwd, this.password).then((isValid) => {
-    return (isValid) ? true : Promise.reject(new Error(lang.t('auth:errors:invalidlogin')))
-  })
-}
+    return wiki.db.User.findOneAndUpdate({
+      email: primaryEmail,
+      provider: profile.provider
+    }, {
+      email: primaryEmail,
+      provider: profile.provider,
+      providerId: profile.id,
+      name: profile.displayName || _.split(primaryEmail, '@')[0]
+    }, {
+      new: true
+    }).then((user) => {
+      // Handle unregistered accounts
+      if (!user && profile.provider !== 'local' && (appconfig.auth.defaultReadAccess || profile.provider === 'ldap' || profile.provider === 'azure')) {
+        let nUsr = {
+          email: primaryEmail,
+          provider: profile.provider,
+          providerId: profile.id,
+          password: '',
+          name: profile.displayName || profile.name || profile.cn,
+          rights: [{
+            role: 'read',
+            path: '/',
+            exact: false,
+            deny: false
+          }]
+        }
+        return wiki.db.User.create(nUsr)
+      }
+      return user || Promise.reject(new Error(wiki.lang.t('auth:errors:notyetauthorized')))
+    })
+  }
 
-module.exports = Mongoose.model('User', userSchema)
+  userSchema.hashPassword = (rawPwd) => {
+    return bcrypt.hash(rawPwd)
+  }
+
+  return userSchema
+}
diff --git a/server/modules/auth.js b/server/modules/auth.js
new file mode 100644
index 00000000..690d0971
--- /dev/null
+++ b/server/modules/auth.js
@@ -0,0 +1,106 @@
+/* global wiki */
+
+const _ = require('lodash')
+const passport = require('passport')
+const fs = require('fs-extra')
+const path = require('path')
+
+module.exports = {
+  strategies: {},
+  init() {
+    this.passport = passport
+
+    // Serialization user methods
+
+    passport.serializeUser(function (user, done) {
+      done(null, user._id)
+    })
+
+    passport.deserializeUser(function (id, done) {
+      wiki.db.User.findById(id).then((user) => {
+        if (user) {
+          done(null, user)
+        } else {
+          done(new Error(wiki.lang.t('auth:errors:usernotfound')), null)
+        }
+        return true
+      }).catch((err) => {
+        done(err, null)
+      })
+    })
+
+    // Load authentication strategies
+
+    wiki.config.auth.strategies.local = {}
+
+    _.forOwn(wiki.config.auth.strategies, (strategyConfig, strategyKey) => {
+      strategyConfig.callbackURL = `${wiki.config.site.host}${wiki.config.site.path}/login/${strategyKey}/callback`
+      let strategy = require(`../authentication/${strategyKey}`)
+      strategy.init(passport, strategyConfig)
+      fs.readFile(path.join(wiki.ROOTPATH, `assets/svg/auth-icon-${strategyKey}.svg`), 'utf8').then(iconData => {
+        strategy.icon = iconData
+      }).catch(err => {
+        if (err.code === 'ENOENT') {
+          strategy.icon = '[missing icon]'
+        } else {
+          wiki.logger.error(err)
+        }
+      })
+      this.strategies[strategy.key] = strategy
+      wiki.logger.info(`Authentication Provider ${strategyKey}: OK`)
+    })
+
+    // Create Guest account for first-time
+
+    wiki.db.User.findOne({
+      where: {
+        provider: 'local',
+        email: 'guest@example.com'
+      }
+    }).then((c) => {
+      if (c < 1) {
+        return wiki.db.User.create({
+          provider: 'local',
+          email: 'guest@example.com',
+          name: 'Guest',
+          password: '',
+          role: 'guest'
+        }).then(() => {
+          wiki.logger.info('[AUTH] Guest account created successfully!')
+          return true
+        }).catch((err) => {
+          wiki.logger.error('[AUTH] An error occured while creating guest account:')
+          wiki.logger.error(err)
+          return err
+        })
+      }
+    })
+
+    // .then(() => {
+    //   if (process.env.WIKI_JS_HEROKU) {
+    //     return wiki.db.User.findOne({ provider: 'local', email: process.env.WIKI_ADMIN_EMAIL }).then((c) => {
+    //       if (c < 1) {
+    //         // Create root admin account (HEROKU ONLY)
+
+    //         return wiki.db.User.create({
+    //           provider: 'local',
+    //           email: process.env.WIKI_ADMIN_EMAIL,
+    //           name: 'Administrator',
+    //           password: '$2a$04$MAHRw785Xe/Jd5kcKzr3D.VRZDeomFZu2lius4gGpZZ9cJw7B7Mna', // admin123 (default)
+    //           role: 'admin'
+    //         }).then(() => {
+    //           wiki.logger.info('[AUTH] Root admin account created successfully!')
+    //           return true
+    //         }).catch((err) => {
+    //           wiki.logger.error('[AUTH] An error occured while creating root admin account:')
+    //           wiki.logger.error(err)
+    //           return err
+    //         })
+    //       } else { return true }
+    //     })
+    //   } else { return true }
+    // })
+
+    return this
+  }
+}
diff --git a/server/modules/config.js b/server/modules/config.js
new file mode 100644
index 00000000..a8e15378
--- /dev/null
+++ b/server/modules/config.js
@@ -0,0 +1,85 @@
+/* global wiki */
+
+const fs = require('fs')
+const yaml = require('js-yaml')
+const _ = require('lodash')
+const path = require('path')
+const cfgHelper = require('../helpers/config')
+
+module.exports = {
+  /**
+   * Load root config from disk
+   */
+  init() {
+    let confPaths = {
+      config: path.join(wiki.ROOTPATH, 'config.yml'),
+      data: path.join(wiki.SERVERPATH, 'app/data.yml'),
+      dataRegex: path.join(wiki.SERVERPATH, 'app/regex.js')
+    }
+
+    let appconfig = {}
+    let appdata = {}
+
+    try {
+      appconfig = yaml.safeLoad(
+        cfgHelper.parseConfigValue(
+          fs.readFileSync(confPaths.config, 'utf8')
+        )
+      )
+      appdata = yaml.safeLoad(fs.readFileSync(confPaths.data, 'utf8'))
+      appdata.regex = require(confPaths.dataRegex)
+    } catch (ex) {
+      console.error(ex)
+      process.exit(1)
+    }
+
+    // Merge with defaults
+
+    appconfig = _.defaultsDeep(appconfig, appdata.defaults.config)
+
+    // Check port
+
+    if (appconfig.port < 1) {
+      appconfig.port = process.env.PORT || 80
+    }
+
+    // Convert booleans
+
+    appconfig.public = (appconfig.public === true || _.toLower(appconfig.public) === 'true')
+
+    // List authentication strategies
+    wiki.config = appconfig
+    wiki.data = appdata
+  },
+
+  /**
+   * Load config from DB
+   *
+   * @param {Array} subsets Array of subsets to load
+   * @returns Promise
+   */
+  loadFromDb(subsets) {
+    if (!_.isArray(subsets) || subsets.length === 0) {
+      subsets = wiki.data.configNamespaces
+    }
+
+    return wiki.db.Setting.findAll({
+      attributes: ['key', 'config'],
+      where: {
+        key: {
+          $in: subsets
+        }
+      }
+    }).then(results => {
+      if (_.isArray(results) && results.length === subsets.length) {
+        results.forEach(result => {
+          wiki.config[result.key] = result.config
+        })
+        return true
+      } else {
+        wiki.logger.warn('DB Configuration is empty or incomplete.')
+        return false
+      }
+    })
+  }
+}
diff --git a/server/modules/db.js b/server/modules/db.js
new file mode 100644
index 00000000..7063f7f1
--- /dev/null
+++ b/server/modules/db.js
@@ -0,0 +1,137 @@
+'use strict'
+
+/* global wiki */
+
+const fs = require('fs')
+const path = require('path')
+const _ = require('lodash')
+const Promise = require('bluebird')
+const Sequelize = require('sequelize')
+const Op = Sequelize.Op
+
+const operatorsAliases = {
+  $eq: Op.eq,
+  $ne: Op.ne,
+  $gte: Op.gte,
+  $gt: Op.gt,
+  $lte: Op.lte,
+  $lt: Op.lt,
+  $not: Op.not,
+  $in: Op.in,
+  $notIn: Op.notIn,
+  $is: Op.is,
+  $like: Op.like,
+  $notLike: Op.notLike,
+  $iLike: Op.iLike,
+  $notILike: Op.notILike,
+  $regexp: Op.regexp,
+  $notRegexp: Op.notRegexp,
+  $iRegexp: Op.iRegexp,
+  $notIRegexp: Op.notIRegexp,
+  $between: Op.between,
+  $notBetween: Op.notBetween,
+  $overlap: Op.overlap,
+  $contains: Op.contains,
+  $contained: Op.contained,
+  $adjacent: Op.adjacent,
+  $strictLeft: Op.strictLeft,
+  $strictRight: Op.strictRight,
+  $noExtendRight: Op.noExtendRight,
+  $noExtendLeft: Op.noExtendLeft,
+  $and: Op.and,
+  $or: Op.or,
+  $any: Op.any,
+  $all: Op.all,
+  $values: Op.values,
+  $col: Op.col
+}
+
+/**
+ * PostgreSQL DB module
+ */
+module.exports = {
+
+  Sequelize,
+  Op: Sequelize.Op,
+
+  /**
+   * Initialize DB
+   *
+   * @return     {Object}  DB instance
+   */
+  init() {
+    let self = this
+
+    let dbModelsPath = path.join(wiki.SERVERPATH, 'models')
+
+    // Define Sequelize instance
+
+    self.inst = new self.Sequelize(wiki.config.db.db, wiki.config.db.user, wiki.config.db.pass, {
+      host: wiki.config.db.host,
+      port: wiki.config.db.port,
+      dialect: 'postgres',
+      pool: {
+        max: 10,
+        min: 0,
+        idle: 10000
+      },
+      logging: log => { wiki.logger.log('verbose', log) },
+      operatorsAliases
+    })
+
+    // Attempt to connect and authenticate to DB
+
+    self.inst.authenticate().then(() => {
+      wiki.logger.info('Database (PostgreSQL) connection: OK')
+    }).catch(err => {
+      wiki.logger.error('Failed to connect to PostgreSQL instance.')
+      return err
+    })
+
+    // Load DB Models
+
+    fs
+      .readdirSync(dbModelsPath)
+      .filter(file => {
+        return (file.indexOf('.') !== 0 && file.indexOf('_') !== 0)
+      })
+      .forEach(file => {
+        let modelName = _.upperFirst(_.camelCase(_.split(file, '.')[0]))
+        self[modelName] = self.inst.import(path.join(dbModelsPath, file))
+      })
+
+    // Associate DB Models
+
+    require(path.join(dbModelsPath, '_relations.js'))(self)
+
+    // Set init tasks
+
+    let initTasks = {
+      // -> Sync DB Schemas
+      syncSchemas() {
+        return self.inst.sync({
+          force: false,
+          logging: log => { wiki.logger.log('verbose', log) }
+        })
+      },
+      // -> Set Connection App Name
+      setAppName() {
+        return self.inst.query(`set application_name = 'Wiki.js'`, { raw: true })
+      }
+    }
+
+    let initTasksQueue = (wiki.IS_MASTER) ? [
+      initTasks.syncSchemas,
+      initTasks.setAppName
+    ] : [
+      initTasks.setAppName
+    ]
+
+    // Perform init tasks
+
+    self.onReady = Promise.each(initTasksQueue, t => t()).return(true)
+
+    return self
+  }
+
+}
diff --git a/server/libs/local.js b/server/modules/disk.js
similarity index 59%
rename from server/libs/local.js
rename to server/modules/disk.js
index 3053e63b..0fafcd68 100644
--- a/server/libs/local.js
+++ b/server/modules/disk.js
@@ -1,6 +1,6 @@
 'use strict'
 
-/* global lang, winston */
+/* global wiki */
 
 const path = require('path')
 const Promise = require('bluebird')
@@ -10,7 +10,7 @@ const os = require('os')
 const _ = require('lodash')
 
 /**
- * Local Data Storage
+ * Local Disk Storage
  */
 module.exports = {
 
@@ -21,29 +21,26 @@ module.exports = {
 
   /**
    * Initialize Local Data Storage model
-   *
-   * @return     {Object}  Local Data Storage model instance
    */
   init () {
-    this._uploadsPath = path.resolve(ROOTPATH, appconfig.paths.repo, 'uploads')
-    this._uploadsThumbsPath = path.resolve(ROOTPATH, appconfig.paths.data, 'thumbs')
+    this._uploadsPath = path.resolve(wiki.ROOTPATH, wiki.config.paths.repo, 'uploads')
+    this._uploadsThumbsPath = path.resolve(wiki.ROOTPATH, wiki.config.paths.data, 'thumbs')
 
-    this.createBaseDirectories(appconfig)
-    this.initMulter(appconfig)
+    this.createBaseDirectories()
+    // this.initMulter()
 
     return this
   },
 
   /**
    * Init Multer upload handlers
-   *
-   * @param      {Object}   appconfig  The application config
-   * @return     {boolean}  Void
    */
-  initMulter (appconfig) {
+  initMulter () {
     let maxFileSizes = {
-      img: appconfig.uploads.maxImageFileSize * 1024 * 1024,
-      file: appconfig.uploads.maxOtherFileSize * 1024 * 1024
+      // img: wiki.config.uploads.maxImageFileSize * 1024 * 1024,
+      // file: wiki.config.uploads.maxOtherFileSize * 1024 * 1024
+      img: 3 * 1024 * 1024,
+      file: 10 * 1024 * 1024
     }
 
     // -> IMAGES
@@ -51,7 +48,7 @@ module.exports = {
     this.uploadImgHandler = multer({
       storage: multer.diskStorage({
         destination: (req, f, cb) => {
-          cb(null, path.resolve(ROOTPATH, appconfig.paths.data, 'temp-upload'))
+          cb(null, path.resolve(wiki.ROOTPATH, wiki.config.paths.data, 'temp-upload'))
         }
       }),
       fileFilter: (req, f, cb) => {
@@ -76,7 +73,7 @@ module.exports = {
     this.uploadFileHandler = multer({
       storage: multer.diskStorage({
         destination: (req, f, cb) => {
-          cb(null, path.resolve(ROOTPATH, appconfig.paths.data, 'temp-upload'))
+          cb(null, path.resolve(wiki.ROOTPATH, wiki.config.paths.data, 'temp-upload'))
         }
       }),
       fileFilter: (req, f, cb) => {
@@ -95,35 +92,30 @@ module.exports = {
 
   /**
    * Creates a base directories (Synchronous).
-   *
-   * @param      {Object}  appconfig  The application config
-   * @return     {Void}  Void
    */
-  createBaseDirectories (appconfig) {
-    winston.info('Checking data directories...')
-
+  createBaseDirectories () {
     try {
-      fs.ensureDirSync(path.resolve(ROOTPATH, appconfig.paths.data))
-      fs.emptyDirSync(path.resolve(ROOTPATH, appconfig.paths.data))
-      fs.ensureDirSync(path.resolve(ROOTPATH, appconfig.paths.data, './cache'))
-      fs.ensureDirSync(path.resolve(ROOTPATH, appconfig.paths.data, './thumbs'))
-      fs.ensureDirSync(path.resolve(ROOTPATH, appconfig.paths.data, './temp-upload'))
+      fs.ensureDirSync(path.resolve(wiki.ROOTPATH, wiki.config.paths.data))
+      fs.emptyDirSync(path.resolve(wiki.ROOTPATH, wiki.config.paths.data))
+      fs.ensureDirSync(path.resolve(wiki.ROOTPATH, wiki.config.paths.data, './cache'))
+      fs.ensureDirSync(path.resolve(wiki.ROOTPATH, wiki.config.paths.data, './thumbs'))
+      fs.ensureDirSync(path.resolve(wiki.ROOTPATH, wiki.config.paths.data, './temp-upload'))
 
       if (os.type() !== 'Windows_NT') {
-        fs.chmodSync(path.resolve(ROOTPATH, appconfig.paths.data, './temp-upload'), '755')
+        fs.chmodSync(path.resolve(wiki.ROOTPATH, wiki.config.paths.data, './temp-upload'), '755')
       }
 
-      fs.ensureDirSync(path.resolve(ROOTPATH, appconfig.paths.repo))
-      fs.ensureDirSync(path.resolve(ROOTPATH, appconfig.paths.repo, './uploads'))
+      fs.ensureDirSync(path.resolve(wiki.ROOTPATH, wiki.config.paths.repo))
+      fs.ensureDirSync(path.resolve(wiki.ROOTPATH, wiki.config.paths.repo, './uploads'))
 
       if (os.type() !== 'Windows_NT') {
-        fs.chmodSync(path.resolve(ROOTPATH, appconfig.paths.repo, './uploads'), '755')
+        fs.chmodSync(path.resolve(wiki.ROOTPATH, wiki.config.paths.repo, './uploads'), '755')
       }
     } catch (err) {
-      winston.error(err)
+      wiki.logger.error(err)
     }
 
-    winston.info('Data and Repository directories are OK.')
+    wiki.logger.info('Disk Data Paths: OK')
   },
 
   /**
@@ -154,7 +146,7 @@ module.exports = {
    */
   validateUploadsFilename (f, fld, isImage) {
     let fObj = path.parse(f)
-    let fname = _.chain(fObj.name).trim().toLower().kebabCase().value().replace(new RegExp('[^a-z0-9-' + appdata.regex.cjk + appdata.regex.arabic + ']', 'g'), '')
+    let fname = _.chain(fObj.name).trim().toLower().kebabCase().value().replace(new RegExp('[^a-z0-9-' + wiki.data.regex.cjk + wiki.data.regex.arabic + ']', 'g'), '')
     let fext = _.toLower(fObj.ext)
 
     if (isImage && !_.includes(['.jpg', '.jpeg', '.png', '.gif', '.webp'], fext)) {
@@ -165,7 +157,7 @@ module.exports = {
     let fpath = path.resolve(this._uploadsPath, fld, f)
 
     return fs.statAsync(fpath).then((s) => {
-      throw new Error(lang.t('errors:fileexists', { path: f }))
+      throw new Error(wiki.lang.t('errors:fileexists', { path: f }))
     }).catch((err) => {
       if (err.code === 'ENOENT') {
         return f
diff --git a/server/libs/entries.js b/server/modules/documents.js
similarity index 97%
rename from server/libs/entries.js
rename to server/modules/documents.js
index af6f1104..8406be0d 100644
--- a/server/libs/entries.js
+++ b/server/modules/documents.js
@@ -1,6 +1,6 @@
 'use strict'
 
-/* global db, git, lang, mark, rights, search, winston */
+/* global wiki */
 
 const Promise = require('bluebird')
 const path = require('path')
@@ -10,7 +10,7 @@ const _ = require('lodash')
 const entryHelper = require('../helpers/entry')
 
 /**
- * Entries Model
+ * Documents Model
  */
 module.exports = {
 
@@ -25,10 +25,10 @@ module.exports = {
   init() {
     let self = this
 
-    self._repoPath = path.resolve(ROOTPATH, appconfig.paths.repo)
-    self._cachePath = path.resolve(ROOTPATH, appconfig.paths.data, 'cache')
-    appdata.repoPath = self._repoPath
-    appdata.cachePath = self._cachePath
+    self._repoPath = path.resolve(wiki.ROOTPATH, wiki.config.paths.repo)
+    self._cachePath = path.resolve(wiki.ROOTPATH, wiki.config.paths.data, 'cache')
+    wiki.data.repoPath = self._repoPath
+    wiki.data.cachePath = self._cachePath
 
     return self
   },
diff --git a/server/libs/git.js b/server/modules/git.js
similarity index 71%
rename from server/libs/git.js
rename to server/modules/git.js
index 7787f37a..68f78e1f 100644
--- a/server/libs/git.js
+++ b/server/modules/git.js
@@ -1,6 +1,6 @@
 'use strict'
 
-/* global lang, winston */
+/* global wiki */
 
 const Git = require('git-wrapper2-promise')
 const Promise = require('bluebird')
@@ -43,21 +43,19 @@ module.exports = {
 
     // -> Build repository path
 
-    if (_.isEmpty(appconfig.paths.repo)) {
-      self._repo.path = path.join(ROOTPATH, 'repo')
+    if (_.isEmpty(wiki.config.paths.repo)) {
+      self._repo.path = path.join(wiki.ROOTPATH, 'repo')
     } else {
-      self._repo.path = appconfig.paths.repo
+      self._repo.path = wiki.config.paths.repo
     }
 
     // -> Initialize repository
 
-    self.onReady = self._initRepo(appconfig)
+    self.onReady = (wiki.IS_MASTER) ? self._initRepo() : Promise.resolve()
 
-    if (appconfig.git) {
-      // Set repo branch
-      self._repo.branch = appconfig.git.branch || 'master'
-      // Define signature
-      self._signature.email = appconfig.git.serverEmail || 'wiki@example.com'
+    if (wiki.config.git) {
+      self._repo.branch = wiki.config.git.branch || 'master'
+      self._signature.email = wiki.config.git.serverEmail || 'wiki@example.com'
     }
 
     return self
@@ -66,19 +64,17 @@ module.exports = {
   /**
    * Initialize Git repository
    *
-   * @param      {Object}  appconfig  The application config
+   * @param      {Object}  wiki.config  The application config
    * @return     {Object}  Promise
    */
-  _initRepo(appconfig) {
+  _initRepo() {
     let self = this
 
-    winston.info('Checking Git repository...')
-
     // -> Check if path is accessible
 
     return fs.mkdirAsync(self._repo.path).catch((err) => {
       if (err.code !== 'EEXIST') {
-        winston.error('Invalid Git repository path or missing permissions.')
+        wiki.logger.error('Invalid Git repository path or missing permissions.')
       }
     }).then(() => {
       self._git = new Git({ 'git-dir': self._repo.path })
@@ -92,28 +88,28 @@ module.exports = {
         self._repo.exists = false
       })
     }).then(() => {
-      if (appconfig.git === false) {
-        winston.info('Remote Git syncing is disabled. Not recommended!')
+      if (wiki.config.git === false) {
+        wiki.logger.warn('Remote Git syncing is disabled. Not recommended!')
         return Promise.resolve(true)
       }
 
       // Initialize remote
 
-      let urlObj = URL.parse(appconfig.git.url)
-      if (appconfig.git.auth.type !== 'ssh') {
-        urlObj.auth = appconfig.git.auth.username + ':' + appconfig.git.auth.password
+      let urlObj = URL.parse(wiki.config.git.url)
+      if (wiki.config.git.auth.type !== 'ssh') {
+        urlObj.auth = wiki.config.git.auth.username + ':' + wiki.config.git.auth.password
       }
       self._url = URL.format(urlObj)
 
       let gitConfigs = [
         () => { return self._git.exec('config', ['--local', 'user.name', 'Wiki']) },
         () => { return self._git.exec('config', ['--local', 'user.email', self._signature.email]) },
-        () => { return self._git.exec('config', ['--local', '--bool', 'http.sslVerify', _.toString(appconfig.git.auth.sslVerify)]) }
+        () => { return self._git.exec('config', ['--local', '--bool', 'http.sslVerify', _.toString(wiki.config.git.auth.sslVerify)]) }
       ]
 
-      if (appconfig.git.auth.type === 'ssh') {
+      if (wiki.config.git.auth.type === 'ssh') {
         gitConfigs.push(() => {
-          return self._git.exec('config', ['--local', 'core.sshCommand', 'ssh -i "' + appconfig.git.auth.privateKey + '" -o StrictHostKeyChecking=no'])
+          return self._git.exec('config', ['--local', 'core.sshCommand', 'ssh -i "' + wiki.config.git.auth.privateKey + '" -o StrictHostKeyChecking=no'])
         })
       }
 
@@ -126,14 +122,14 @@ module.exports = {
             return self._git.exec('remote', ['set-url', 'origin', self._url])
           }
         }).catch(err => {
-          winston.error(err)
+          wiki.logger.error(err)
         })
       })
     }).catch((err) => {
-      winston.error('Git remote error!')
+      wiki.logger.error('Git remote error!')
       throw err
     }).then(() => {
-      winston.info('Git repository is OK.')
+      wiki.logger.info('Git Repository: OK')
       return true
     })
   },
@@ -144,7 +140,7 @@ module.exports = {
    * @return     {String}  The repo path.
    */
   getRepoPath() {
-    return this._repo.path || path.join(ROOTPATH, 'repo')
+    return this._repo.path || path.join(wiki.ROOTPATH, 'repo')
   },
 
   /**
@@ -157,18 +153,18 @@ module.exports = {
 
     // Is git remote disabled?
 
-    if (appconfig.git === false) {
+    if (wiki.config.git === false) {
       return Promise.resolve(true)
     }
 
     // Fetch
 
-    winston.info('Performing pull from remote Git repository...')
+    wiki.logger.info('Performing pull from remote Git repository...')
     return self._git.pull('origin', self._repo.branch).then((cProc) => {
-      winston.info('Git Pull completed.')
+      wiki.logger.info('Git Pull completed.')
     })
       .catch((err) => {
-        winston.error('Unable to fetch from git origin!')
+        wiki.logger.error('Unable to fetch from git origin!')
         throw err
       })
       .then(() => {
@@ -178,19 +174,19 @@ module.exports = {
           let out = cProc.stdout.toString()
 
           if (_.includes(out, 'commit')) {
-            winston.info('Performing push to remote Git repository...')
+            wiki.logger.info('Performing push to remote Git repository...')
             return self._git.push('origin', self._repo.branch).then(() => {
-              return winston.info('Git Push completed.')
+              return wiki.logger.info('Git Push completed.')
             })
           } else {
-            winston.info('Git Push skipped. Repository is already in sync.')
+            wiki.logger.info('Git Push skipped. Repository is already in sync.')
           }
 
           return true
         })
       })
       .catch((err) => {
-        winston.error('Unable to push changes to remote Git repository!')
+        wiki.logger.error('Unable to push changes to remote Git repository!')
         throw err
       })
   },
@@ -210,7 +206,7 @@ module.exports = {
       let out = cProc.stdout.toString()
       return _.includes(out, gitFilePath)
     }).then((isTracked) => {
-      commitMsg = (isTracked) ? lang.t('git:updated', { path: gitFilePath }) : lang.t('git:added', { path: gitFilePath })
+      commitMsg = (isTracked) ? wiki.lang.t('git:updated', { path: gitFilePath }) : wiki.lang.t('git:added', { path: gitFilePath })
       return self._git.add(gitFilePath)
     }).then(() => {
       let commitUsr = securityHelper.sanitizeCommitUser(author)
@@ -245,29 +241,6 @@ module.exports = {
     })
   },
 
-  /**
-   * Delete a document.
-   *
-   * @param      {String}            entryPath     The entry path
-   * @return     {Promise<Boolean>}  Resolve on success
-   */
-  deleteDocument(entryPath, author) {
-    let self = this
-    let gitFilePath = entryPath + '.md'
-
-    return this._git.exec('rm', [gitFilePath]).then((cProc) => {
-      let out = cProc.stdout.toString()
-      if (_.includes(out, 'fatal')) {
-        let errorMsg = _.capitalize(_.head(_.split(_.replace(out, 'fatal: ', ''), ',')))
-        throw new Error(errorMsg)
-      }
-      let commitUsr = securityHelper.sanitizeCommitUser(author)
-      return self._git.exec('commit', ['-m', lang.t('git:deleted', { path: gitFilePath }), '--author="' + commitUsr.name + ' <' + commitUsr.email + '>"']).catch((err) => {
-        if (_.includes(err.stdout, 'nothing to commit')) { return true }
-      })
-    })
-  },
-
   /**
    * Commits uploads changes.
    *
diff --git a/server/modules/graphql.js b/server/modules/graphql.js
new file mode 100644
index 00000000..aa6a6f7d
--- /dev/null
+++ b/server/modules/graphql.js
@@ -0,0 +1,43 @@
+'use strict'
+
+/* global wiki */
+
+const gqlTools = require('graphql-tools')
+const fs = require('fs')
+const path = require('path')
+const _ = require('lodash')
+
+const typeDefs = fs.readFileSync(path.join(wiki.SERVERPATH, 'schemas/types.graphql'), 'utf8')
+
+const DateScalar = require('../schemas/scalar-date')
+const AuthenticationResolvers = require('../schemas/resolvers-authentication')
+const CommentResolvers = require('../schemas/resolvers-comment')
+const DocumentResolvers = require('../schemas/resolvers-document')
+const FileResolvers = require('../schemas/resolvers-file')
+const FolderResolvers = require('../schemas/resolvers-folder')
+const GroupResolvers = require('../schemas/resolvers-group')
+const SettingResolvers = require('../schemas/resolvers-setting')
+const TagResolvers = require('../schemas/resolvers-tag')
+const TranslationResolvers = require('../schemas/resolvers-translation')
+const UserResolvers = require('../schemas/resolvers-user')
+
+const resolvers = _.merge(
+  AuthenticationResolvers,
+  CommentResolvers,
+  DocumentResolvers,
+  FileResolvers,
+  FolderResolvers,
+  GroupResolvers,
+  SettingResolvers,
+  TagResolvers,
+  TranslationResolvers,
+  UserResolvers,
+  DateScalar
+)
+
+const Schema = gqlTools.makeExecutableSchema({
+  typeDefs,
+  resolvers
+})
+
+module.exports = Schema
diff --git a/server/modules/kernel.js b/server/modules/kernel.js
new file mode 100644
index 00000000..48e1659f
--- /dev/null
+++ b/server/modules/kernel.js
@@ -0,0 +1,91 @@
+const cluster = require('cluster')
+const Promise = require('bluebird')
+const _ = require('lodash')
+
+/* global wiki */
+
+module.exports = {
+  numWorkers: 1,
+  workers: [],
+  init() {
+    if (cluster.isMaster) {
+      wiki.logger.info('=======================================')
+      wiki.logger.info('= Wiki.js =============================')
+      wiki.logger.info('=======================================')
+
+      wiki.redis = require('./redis').init()
+      wiki.queue = require('./queue').init()
+
+      this.setWorkerLimit()
+      this.bootMaster()
+    } else {
+      this.bootWorker()
+    }
+  },
+  /**
+   * Pre-Master Boot Sequence
+   */
+  preBootMaster() {
+    return Promise.mapSeries([
+      () => { return wiki.db.onReady },
+      () => { return wiki.configSvc.loadFromDb() },
+      () => { return wiki.queue.clean() }
+    ], fn => { return fn() })
+  },
+  /**
+   * Boot Master Process
+   */
+  bootMaster() {
+    this.preBootMaster().then(sequenceResults => {
+      if (_.every(sequenceResults, rs => rs === true)) {
+        this.postBootMaster()
+      } else {
+        wiki.logger.info('Starting configuration manager...')
+        require('../configure')()
+      }
+      return true
+    }).catch(err => {
+      wiki.logger.error(err)
+      process.exit(1)
+    })
+  },
+  /**
+   * Post-Master Boot Sequence
+   */
+  postBootMaster() {
+    require('../master')().then(() => {
+      _.times(this.numWorker, this.spawnWorker)
+
+      wiki.queue.uplClearTemp.add({}, {
+        repeat: { cron: '*/15 * * * *' }
+      })
+    })
+
+    cluster.on('exit', (worker, code, signal) => {
+      wiki.logger.info(`Background Worker #${worker.id} was terminated.`)
+    })
+  },
+  /**
+   * Boot Worker Process
+   */
+  bootWorker() {
+    wiki.logger.info(`Background Worker #${cluster.worker.id} is initializing...`)
+    require('../worker')
+  },
+  /**
+   * Spawn new Worker process
+   */
+  spawnWorker() {
+    this.workers.push(cluster.fork())
+  },
+  /**
+   * Set Worker count based on config + system capabilities
+   */
+  setWorkerLimit() {
+    const numCPUs = require('os').cpus().length
+    this.numWorkers = (wiki.config.workers > 0) ? wiki.config.workers : numCPUs
+    if (this.numWorkers > numCPUs) {
+      this.numWorkers = numCPUs
+    }
+  }
+}
diff --git a/server/modules/localization.js b/server/modules/localization.js
new file mode 100644
index 00000000..d832935b
--- /dev/null
+++ b/server/modules/localization.js
@@ -0,0 +1,52 @@
+const _ = require('lodash')
+const dotize = require('dotize')
+const i18nBackend = require('i18next-node-fs-backend')
+const i18next = require('i18next')
+const path = require('path')
+const Promise = require('bluebird')
+
+/* global wiki */
+
+module.exports = {
+  engine: null,
+  namespaces: ['common', 'admin', 'auth', 'errors', 'git'],
+  init() {
+    this.engine = i18next
+    this.engine.use(i18nBackend).init({
+      load: 'languageOnly',
+      ns: this.namespaces,
+      defaultNS: 'common',
+      saveMissing: false,
+      preload: [wiki.config.site.lang],
+      lng: wiki.config.site.lang,
+      fallbackLng: 'en',
+      backend: {
+        loadPath: path.join(wiki.SERVERPATH, 'locales/{{lng}}/{{ns}}.json')
+      }
+    })
+    return this
+  },
+  getByNamespace(locale, namespace) {
+    if (this.engine.hasResourceBundle(locale, namespace)) {
+      let data = this.engine.getResourceBundle(locale, namespace)
+      return _.map(dotize.convert(data), (value, key) => {
+        return {
+          key,
+          value
+        }
+      })
+    } else {
+      throw new Error('Invalid locale or namespace')
+    }
+  },
+  loadLocale(locale) {
+    return Promise.fromCallback(cb => {
+      return this.engine.loadLanguages(locale, cb)
+    })
+  },
+  setCurrentLocale(locale) {
+    return Promise.fromCallback(cb => {
+      return this.engine.changeLanguage(locale, cb)
+    })
+  }
+}
diff --git a/server/modules/logger.js b/server/modules/logger.js
new file mode 100644
index 00000000..8b134d05
--- /dev/null
+++ b/server/modules/logger.js
@@ -0,0 +1,80 @@
+'use strict'
+
+/* global wiki */
+
+const cluster = require('cluster')
+
+module.exports = {
+  init() {
+    let winston = require('winston')
+
+    // Console
+
+    let logger = new (winston.Logger)({
+      level: (wiki.IS_DEBUG) ? 'debug' : 'info',
+      transports: [
+        new (winston.transports.Console)({
+          level: (wiki.IS_DEBUG) ? 'debug' : 'info',
+          prettyPrint: true,
+          colorize: true,
+          silent: false,
+          timestamp: true
+        })
+      ]
+    })
+
+    logger.filters.push((level, msg) => {
+      let processName = (cluster.isMaster) ? 'MASTER' : `WORKER-${cluster.worker.id}`
+      return '[' + processName + '] ' + msg
+    })
+
+    // External services
+
+    // if (wiki.config.externalLogging.bugsnag) {
+    //   const bugsnagTransport = require('./winston-transports/bugsnag')
+    //   logger.add(bugsnagTransport, {
+    //     level: 'warn',
+    //     key: wiki.config.externalLogging.bugsnag
+    //   })
+    // }
+
+    // if (wiki.config.externalLogging.loggly) {
+    //   require('winston-loggly-bulk')
+    //   logger.add(winston.transports.Loggly, {
+    //     token: wiki.config.externalLogging.loggly.token,
+    //     subdomain: wiki.config.externalLogging.loggly.subdomain,
+    //     tags: ['wiki-js'],
+    //     level: 'warn',
+    //     json: true
+    //   })
+    // }
+
+    // if (wiki.config.externalLogging.papertrail) {
+    //   require('winston-papertrail').Papertrail // eslint-disable-line no-unused-expressions
+    //   logger.add(winston.transports.Papertrail, {
+    //     host: wiki.config.externalLogging.papertrail.host,
+    //     port: wiki.config.externalLogging.papertrail.port,
+    //     level: 'warn',
+    //     program: 'wiki.js'
+    //   })
+    // }
+
+    // if (wiki.config.externalLogging.rollbar) {
+    //   const rollbarTransport = require('./winston-transports/rollbar')
+    //   logger.add(rollbarTransport, {
+    //     level: 'warn',
+    //     key: wiki.config.externalLogging.rollbar
+    //   })
+    // }
+
+    // if (wiki.config.externalLogging.sentry) {
+    //   const sentryTransport = require('./winston-transports/sentry')
+    //   logger.add(sentryTransport, {
+    //     level: 'warn',
+    //     key: wiki.config.externalLogging.sentry
+    //   })
+    // }
+
+    return logger
+  }
+}
diff --git a/server/libs/markdown.js b/server/modules/markdown.js
similarity index 96%
rename from server/libs/markdown.js
rename to server/modules/markdown.js
index 14b0c887..71e0ea54 100644
--- a/server/libs/markdown.js
+++ b/server/modules/markdown.js
@@ -1,6 +1,6 @@
 'use strict'
 
-/* global winston */
+/* global wiki */
 
 const Promise = require('bluebird')
 const md = require('markdown-it')
@@ -23,11 +23,12 @@ const mdRemove = require('remove-markdown')
 
 var mkdown = md({
   html: true,
-  breaks: appconfig.features.linebreaks,
+  // breaks: wiki.config.features.linebreaks,
+  breaks: true,
   linkify: true,
   typography: true,
   highlight(str, lang) {
-    if (appconfig.theme.code.colorize && lang && hljs.getLanguage(lang)) {
+    if (wiki.config.theme.code.colorize && lang && hljs.getLanguage(lang)) {
       try {
         return '<pre class="hljs"><code>' + hljs.highlight(lang, str, true).value + '</code></pre>'
       } catch (err) {
@@ -57,7 +58,8 @@ var mkdown = md({
   })
   .use(mdAttrs)
 
-if (appconfig.features.mathjax) {
+// if (wiki.config.features.mathjax) {
+if (true) {
   mkdown.use(mdMathjax)
 }
 
@@ -94,7 +96,7 @@ const videoRules = [
 
 // Regex
 
-const textRegex = new RegExp('\\b[a-z0-9-.,' + appdata.regex.cjk + appdata.regex.arabic + ']+\\b', 'g')
+const textRegex = new RegExp('\\b[a-z0-9-.,' + wiki.data.regex.cjk + wiki.data.regex.arabic + ']+\\b', 'g')
 const mathRegex = [
   {
     format: 'TeX',
@@ -301,7 +303,7 @@ const parseContent = (content) => {
 
   // Mathjax Post-processor
 
-  if (appconfig.features.mathjax) {
+  if (wiki.config.features.mathjax) {
     return processMathjax(cr.html())
   } else {
     return Promise.resolve(cr.html())
@@ -339,7 +341,7 @@ const processMathjax = (content) => {
                 resolve(result.svg)
               } else {
                 resolve(currentMatch[0])
-                winston.warn(result.errors.join(', '))
+                wiki.logger.warn(result.errors.join(', '))
               }
             })
           })
diff --git a/server/modules/queue.js b/server/modules/queue.js
new file mode 100644
index 00000000..4bbb6dc0
--- /dev/null
+++ b/server/modules/queue.js
@@ -0,0 +1,37 @@
+'use strict'
+
+/* global wiki */
+
+const Bull = require('bull')
+const Promise = require('bluebird')
+
+module.exports = {
+  init() {
+    wiki.data.queues.forEach(queueName => {
+      this[queueName] = new Bull(queueName, {
+        prefix: `q-${wiki.config.ha.nodeuid}`,
+        redis: wiki.config.redis
+      })
+    })
+    return this
+  },
+  clean() {
+    return Promise.each(wiki.data.queues, queueName => {
+      return new Promise((resolve, reject) => {
+        let keyStream = wiki.redis.scanStream({
+          match: `q-${wiki.config.ha.nodeuid}:${queueName}:*`
+        })
+        keyStream.on('data', resultKeys => {
+          if (resultKeys.length > 0) {
+            wiki.redis.del(resultKeys)
+          }
+        })
+        keyStream.on('end', resolve)
+      })
+    }).then(() => {
+      wiki.logger.info('Purging old queue jobs: OK')
+    }).return(true).catch(err => {
+      wiki.logger.error(err)
+    })
+  }
+}
diff --git a/server/modules/redis.js b/server/modules/redis.js
new file mode 100644
index 00000000..6eb7999b
--- /dev/null
+++ b/server/modules/redis.js
@@ -0,0 +1,33 @@
+'use strict'
+
+/* global wiki */
+
+const Redis = require('ioredis')
+const { isPlainObject } = require('lodash')
+
+/**
+ * Redis module
+ *
+ * @return     {Object}  Redis client wrapper instance
+ */
+module.exports = {
+
+  /**
+   * Initialize Redis client
+   *
+   * @return     {Object}  Redis client instance
+   */
+  init() {
+    if (isPlainObject(wiki.config.redis)) {
+      let red = new Redis(wiki.config.redis)
+      red.on('ready', () => {
+        wiki.logger.info('Redis connection: OK')
+      })
+      return red
+    } else {
+      wiki.logger.error('Invalid Redis configuration!')
+      process.exit(1)
+    }
+  }
+
+}
diff --git a/server/libs/rights.js b/server/modules/rights.js
similarity index 94%
rename from server/libs/rights.js
rename to server/modules/rights.js
index ce82882b..d06de758 100644
--- a/server/libs/rights.js
+++ b/server/modules/rights.js
@@ -1,6 +1,6 @@
 'use strict'
 
-/* global db */
+/* global wiki */
 
 const _ = require('lodash')
 
@@ -32,8 +32,8 @@ module.exports = {
   init () {
     let self = this
 
-    db.onReady.then(() => {
-      db.User.findOne({ provider: 'local', email: 'guest' }).then((u) => {
+    wiki.db.onReady.then(() => {
+      wiki.db.User.findOne({ provider: 'local', email: 'guest' }).then((u) => {
         if (u) {
           self.guest = u
         }
diff --git a/server/libs/search.js b/server/modules/search.js
similarity index 87%
rename from server/libs/search.js
rename to server/modules/search.js
index 7c446b17..7801a739 100644
--- a/server/libs/search.js
+++ b/server/modules/search.js
@@ -1,13 +1,13 @@
 'use strict'
 
-/* global winston */
+/* global wiki */
 
 const Promise = require('bluebird')
 const _ = require('lodash')
-const searchIndex = require('./search-index')
+// const searchIndex = require('./search-index')
 const stopWord = require('stopword')
 const streamToPromise = require('stream-to-promise')
-const searchAllowedChars = new RegExp('[^a-z0-9' + appdata.regex.cjk + appdata.regex.arabic + ' ]', 'g')
+const searchAllowedChars = new RegExp('[^a-z0-9' + wiki.data.regex.cjk + wiki.data.regex.arabic + ' ]', 'g')
 
 module.exports = {
 
@@ -22,24 +22,24 @@ module.exports = {
   init () {
     let self = this
     self._isReady = new Promise((resolve, reject) => {
-      searchIndex({
+      /*searchIndex({
         deletable: true,
         fieldedSearch: true,
         indexPath: 'wiki',
         logLevel: 'error',
-        stopwords: _.get(stopWord, appconfig.lang, [])
+        stopwords: _.get(stopWord, wiki.config.lang, [])
       }, (err, si) => {
         if (err) {
-          winston.error('Failed to initialize search index.', err)
+          wiki.logger.error('Failed to initialize search index.', err)
           reject(err)
         } else {
           self._si = Promise.promisifyAll(si)
           self._si.flushAsync().then(() => {
-            winston.info('Search index flushed and ready.')
+            wiki.logger.info('Search index flushed and ready.')
             resolve(true)
           })
         }
-      })
+      }) */
     })
 
     return self
@@ -95,13 +95,13 @@ module.exports = {
           parent: content.parent || '',
           content: content.text || ''
         }]).then(() => {
-          winston.log('verbose', 'Entry ' + content._id + ' added/updated to search index.')
+          wiki.logger.log('verbose', 'Entry ' + content._id + ' added/updated to search index.')
           return true
         }).catch((err) => {
-          winston.error(err)
+          wiki.logger.error(err)
         })
       }).catch((err) => {
-        winston.error(err)
+        wiki.logger.error(err)
       })
     })
   },
@@ -131,7 +131,7 @@ module.exports = {
         if (err.type === 'NotFoundError') {
           return true
         } else {
-          winston.error(err)
+          wiki.logger.error(err)
         }
       })
     })
@@ -204,7 +204,7 @@ module.exports = {
           suggest: []
         }
       } else {
-        winston.error(err)
+        wiki.logger.error(err)
       }
     })
   }
diff --git a/server/libs/system.js b/server/modules/system.js
similarity index 100%
rename from server/libs/system.js
rename to server/modules/system.js
diff --git a/server/libs/uploads-agent.js b/server/modules/uploads-agent.js
similarity index 88%
rename from server/libs/uploads-agent.js
rename to server/modules/uploads-agent.js
index a8ae79ec..6b861733 100644
--- a/server/libs/uploads-agent.js
+++ b/server/modules/uploads-agent.js
@@ -1,6 +1,6 @@
 'use strict'
 
-/* global db, git, lang, upl */
+/* global wiki */
 
 const path = require('path')
 const Promise = require('bluebird')
@@ -32,8 +32,8 @@ module.exports = {
   init () {
     let self = this
 
-    self._uploadsPath = path.resolve(ROOTPATH, appconfig.paths.repo, 'uploads')
-    self._uploadsThumbsPath = path.resolve(ROOTPATH, appconfig.paths.data, 'thumbs')
+    self._uploadsPath = path.resolve(wiki.ROOTPATH, wiki.config.paths.repo, 'uploads')
+    self._uploadsThumbsPath = path.resolve(wiki.ROOTPATH, wiki.config.paths.data, 'thumbs')
 
     return self
   },
@@ -59,16 +59,16 @@ module.exports = {
     self._watcher.on('add', (p) => {
       let pInfo = self.parseUploadsRelPath(p)
       return self.processFile(pInfo.folder, pInfo.filename).then((mData) => {
-        return db.UplFile.findByIdAndUpdate(mData._id, mData, { upsert: true })
+        return wiki.db.UplFile.findByIdAndUpdate(mData._id, mData, { upsert: true })
       }).then(() => {
-        return git.commitUploads(lang.t('git:uploaded', { path: p }))
+        return wiki.git.commitUploads(wiki.lang.t('git:uploaded', { path: p }))
       })
     })
 
     // -> Remove upload file
 
     self._watcher.on('unlink', (p) => {
-      return git.commitUploads(lang.t('git:deleted', { path: p }))
+      return wiki.git.commitUploads(wiki.lang.t('git:deleted', { path: p }))
     })
   },
 
@@ -91,8 +91,8 @@ module.exports = {
 
         // Add folders to DB
 
-        return db.UplFolder.remove({}).then(() => {
-          return db.UplFolder.insertMany(_.map(folderNames, (f) => {
+        return wiki.db.UplFolder.remove({}).then(() => {
+          return wiki.db.UplFolder.insertMany(_.map(folderNames, (f) => {
             return {
               _id: 'f:' + f,
               name: f
@@ -107,7 +107,7 @@ module.exports = {
             let fldPath = path.join(self._uploadsPath, fldName)
             return fs.readdirAsync(fldPath).then((fList) => {
               return Promise.map(fList, (f) => {
-                return upl.processFile(fldName, f).then((mData) => {
+                return wiki.upl.processFile(fldName, f).then((mData) => {
                   if (mData) {
                     allFiles.push(mData)
                   }
@@ -118,9 +118,9 @@ module.exports = {
           }, {concurrency: 1}).finally(() => {
             // Add files to DB
 
-            return db.UplFile.remove({}).then(() => {
+            return wiki.db.UplFile.remove({}).then(() => {
               if (_.isArray(allFiles) && allFiles.length > 0) {
-                return db.UplFile.insertMany(allFiles)
+                return wiki.db.UplFile.insertMany(allFiles)
               } else {
                 return true
               }
@@ -131,7 +131,7 @@ module.exports = {
     }).then(() => {
       // Watch for new changes
 
-      return upl.watch()
+      return wiki.upl.watch()
     })
   },
 
diff --git a/server/libs/uploads.js b/server/modules/uploads.js
similarity index 81%
rename from server/libs/uploads.js
rename to server/modules/uploads.js
index 2bee6322..f56ecab3 100644
--- a/server/libs/uploads.js
+++ b/server/modules/uploads.js
@@ -1,6 +1,6 @@
 'use strict'
 
-/* global db, lang, lcdata, upl, winston */
+/* global wiki */
 
 const path = require('path')
 const Promise = require('bluebird')
@@ -27,8 +27,8 @@ module.exports = {
    * @return     {Object}  Uploads model instance
    */
   init () {
-    this._uploadsPath = path.resolve(ROOTPATH, appconfig.paths.repo, 'uploads')
-    this._uploadsThumbsPath = path.resolve(ROOTPATH, appconfig.paths.data, 'thumbs')
+    this._uploadsPath = path.resolve(wiki.ROOTPATH, wiki.config.paths.repo, 'uploads')
+    this._uploadsThumbsPath = path.resolve(wiki.ROOTPATH, wiki.config.paths.data, 'thumbs')
 
     return this
   },
@@ -48,7 +48,7 @@ module.exports = {
    * @return     {Array<String>}  The uploads folders.
    */
   getUploadsFolders () {
-    return db.UplFolder.find({}, 'name').sort('name').exec().then((results) => {
+    return wiki.db.Folder.find({}, 'name').sort('name').exec().then((results) => {
       return (results) ? _.map(results, 'name') : [{ name: '' }]
     })
   },
@@ -69,7 +69,7 @@ module.exports = {
     }
 
     return fs.ensureDirAsync(path.join(self._uploadsPath, folderName)).then(() => {
-      return db.UplFolder.findOneAndUpdate({
+      return wiki.db.UplFolder.findOneAndUpdate({
         _id: 'f:' + folderName
       }, {
         name: folderName
@@ -88,7 +88,7 @@ module.exports = {
    * @return     {Boolean}   True if valid
    */
   validateUploadsFolder (folderName) {
-    return db.UplFolder.findOne({ name: folderName }).then((f) => {
+    return wiki.db.UplFolder.findOne({ name: folderName }).then((f) => {
       return (f) ? path.resolve(this._uploadsPath, folderName) : false
     })
   },
@@ -101,7 +101,7 @@ module.exports = {
    */
   addUploadsFiles (arrFiles) {
     if (_.isArray(arrFiles) || _.isPlainObject(arrFiles)) {
-      // this._uploadsDb.Files.insert(arrFiles);
+      // this._uploadswiki.Db.Files.insert(arrFiles);
     }
   },
 
@@ -113,7 +113,7 @@ module.exports = {
    * @return     {Array<Object>}  The files matching the query
    */
   getUploadsFiles (cat, fld) {
-    return db.UplFile.find({
+    return wiki.db.UplFile.find({
       category: cat,
       folder: 'f:' + fld
     }).sort('filename').exec()
@@ -128,7 +128,7 @@ module.exports = {
   deleteUploadsFile (uid) {
     let self = this
 
-    return db.UplFile.findOneAndRemove({ _id: uid }).then((f) => {
+    return wiki.db.UplFile.findOneAndRemove({ _id: uid }).then((f) => {
       if (f) {
         return self.deleteUploadsFileTry(f, 0)
       }
@@ -150,7 +150,7 @@ module.exports = {
           return self.deleteUploadsFileTry(f, attempt + 1)
         })
       } else {
-        winston.warn('Unable to delete uploads file ' + f.filename + '. File is locked by another process and multiple attempts failed.')
+        wiki.logger.warn('Unable to delete uploads file ' + f.filename + '. File is locked by another process and multiple attempts failed.')
         return true
       }
     })
@@ -168,12 +168,12 @@ module.exports = {
     let fUrlFilename = _.last(_.split(fUrlObj.pathname, '/'))
     let destFolder = _.chain(fFolder).trim().toLower().value()
 
-    return upl.validateUploadsFolder(destFolder).then((destFolderPath) => {
+    return wiki.upl.validateUploadsFolder(destFolder).then((destFolderPath) => {
       if (!destFolderPath) {
-        return Promise.reject(new Error(lang.t('errors:invalidfolder')))
+        return Promise.reject(new Error(wiki.lang.t('errors:invalidfolder')))
       }
 
-      return lcdata.validateUploadsFilename(fUrlFilename, destFolder).then((destFilename) => {
+      return wiki.disk.validateUploadsFilename(fUrlFilename, destFolder).then((destFilename) => {
         let destFilePath = path.resolve(destFolderPath, destFilename)
 
         return new Promise((resolve, reject) => {
@@ -194,7 +194,7 @@ module.exports = {
               rq.abort()
               destFileStream.destroy()
               fs.remove(destFilePath)
-              reject(new Error(lang.t('errors:remotetoolarge')))
+              reject(new Error(wiki.lang.t('errors:remotetoolarge')))
             }
           }).on('error', (err) => {
             destFileStream.destroy()
@@ -223,15 +223,15 @@ module.exports = {
   moveUploadsFile (uid, fld, nFilename) {
     let self = this
 
-    return db.UplFolder.findById('f:' + fld).then((folder) => {
+    return wiki.db.UplFolder.finwiki.dById('f:' + fld).then((folder) => {
       if (folder) {
-        return db.UplFile.findById(uid).then((originFile) => {
+        return wiki.db.UplFile.finwiki.dById(uid).then((originFile) => {
           // -> Check if rename is valid
 
           let nameCheck = null
           if (nFilename) {
             let originFileObj = path.parse(originFile.filename)
-            nameCheck = lcdata.validateUploadsFilename(nFilename + originFileObj.ext, folder.name)
+            nameCheck = wiki.disk.validateUploadsFilename(nFilename + originFileObj.ext, folder.name)
           } else {
             nameCheck = Promise.resolve(originFile.filename)
           }
@@ -245,12 +245,12 @@ module.exports = {
             // -> Check for invalid operations
 
             if (sourceFilePath === destFilePath) {
-              return Promise.reject(new Error(lang.t('errors:invalidoperation')))
+              return Promise.reject(new Error(wiki.lang.t('errors:invalidoperation')))
             }
 
-            // -> Delete DB entry
+            // -> Delete wiki.DB entry
 
-            preMoveOps.push(db.UplFile.findByIdAndRemove(uid))
+            preMoveOps.push(wiki.db.UplFile.finwiki.dByIdAndRemove(uid))
 
             // -> Move thumbnail ahead to avoid re-generation
 
@@ -273,7 +273,7 @@ module.exports = {
           })
         })
       } else {
-        return Promise.reject(new Error(lang.t('errors:invaliddestfolder')))
+        return Promise.reject(new Error(wiki.lang.t('errors:invaliddestfolder')))
       }
     })
   }
diff --git a/server/libs/winston-transports/bugsnag.js b/server/modules/winston-transports/bugsnag.js
similarity index 100%
rename from server/libs/winston-transports/bugsnag.js
rename to server/modules/winston-transports/bugsnag.js
diff --git a/server/libs/winston-transports/rollbar.js b/server/modules/winston-transports/rollbar.js
similarity index 100%
rename from server/libs/winston-transports/rollbar.js
rename to server/modules/winston-transports/rollbar.js
diff --git a/server/libs/winston-transports/sentry.js b/server/modules/winston-transports/sentry.js
similarity index 100%
rename from server/libs/winston-transports/sentry.js
rename to server/modules/winston-transports/sentry.js
diff --git a/server/queues/git-sync.js b/server/queues/git-sync.js
new file mode 100644
index 00000000..6c46e8ef
--- /dev/null
+++ b/server/queues/git-sync.js
@@ -0,0 +1,68 @@
+'use strict'
+
+/* global wiki */
+
+const Promise = require('bluebird')
+const fs = Promise.promisifyAll(require('fs-extra'))
+const klaw = require('klaw')
+const moment = require('moment')
+const path = require('path')
+const entryHelper = require('../helpers/entry')
+
+module.exports = (job) => {
+  return wiki.git.resync().then(() => {
+    // -> Stream all documents
+
+    let cacheJobs = []
+    let jobCbStreamDocsResolve = null
+    let jobCbStreamDocs = new Promise((resolve, reject) => {
+      jobCbStreamDocsResolve = resolve
+    })
+
+    klaw(wiki.REPOPATH).on('data', function (item) {
+      if (path.extname(item.path) === '.md' && path.basename(item.path) !== 'README.md') {
+        let entryPath = entryHelper.parsePath(entryHelper.getEntryPathFromFullPath(item.path))
+        let cachePath = entryHelper.getCachePath(entryPath)
+
+        // -> Purge outdated cache
+
+        cacheJobs.push(
+          fs.statAsync(cachePath).then((st) => {
+            return moment(st.mtime).isBefore(item.stats.mtime) ? 'expired' : 'active'
+          }).catch((err) => {
+            return (err.code !== 'EEXIST') ? err : 'new'
+          }).then((fileStatus) => {
+            // -> Delete expired cache file
+
+            if (fileStatus === 'expired') {
+              return fs.unlinkAsync(cachePath).return(fileStatus)
+            }
+
+            return fileStatus
+          }).then((fileStatus) => {
+            // -> Update cache and search index
+
+            if (fileStatus !== 'active') {
+              return global.entries.updateCache(entryPath).then(entry => {
+                process.send({
+                  action: 'searchAdd',
+                  content: entry
+                })
+                return true
+              })
+            }
+
+            return true
+          })
+        )
+      }
+    }).on('end', () => {
+      jobCbStreamDocsResolve(Promise.all(cacheJobs))
+    })
+
+    return jobCbStreamDocs
+  }).then(() => {
+    wiki.logger.info('Git remote repository sync: DONE')
+    return true
+  })
+}
diff --git a/server/queues/upl-clear-temp.js b/server/queues/upl-clear-temp.js
new file mode 100644
index 00000000..9c3a1b5b
--- /dev/null
+++ b/server/queues/upl-clear-temp.js
@@ -0,0 +1,29 @@
+'use strict'
+
+/* global wiki */
+
+const Promise = require('bluebird')
+const fs = Promise.promisifyAll(require('fs-extra'))
+const moment = require('moment')
+const path = require('path')
+
+module.exports = (job) => {
+  return fs.readdirAsync(wiki.UPLTEMPPATH).then((ls) => {
+    let fifteenAgo = moment().subtract(15, 'minutes')
+
+    return Promise.map(ls, (f) => {
+      return fs.statAsync(path.join(wiki.UPLTEMPPATH, f)).then((s) => { return { filename: f, stat: s } })
+    }).filter((s) => { return s.stat.isFile() }).then((arrFiles) => {
+      return Promise.map(arrFiles, (f) => {
+        if (moment(f.stat.ctime).isBefore(fifteenAgo, 'minute')) {
+          return fs.unlinkAsync(path.join(wiki.UPLTEMPPATH, f.filename))
+        } else {
+          return true
+        }
+      })
+    })
+  }).then(() => {
+    wiki.logger.info('Purging temporary upload files: DONE')
+    return true
+  })
+}
diff --git a/server/schemas/resolvers-authentication.js b/server/schemas/resolvers-authentication.js
new file mode 100644
index 00000000..572c9d37
--- /dev/null
+++ b/server/schemas/resolvers-authentication.js
@@ -0,0 +1,40 @@
+const _ = require('lodash')
+const fs = require('fs-extra')
+const path = require('path')
+
+/* global wiki */
+
+module.exports = {
+  Query: {
+    authentication(obj, args, context, info) {
+      switch (args.mode) {
+        case 'active':
+          let strategies = _.chain(wiki.auth.strategies).map(str => {
+            return {
+              key: str.key,
+              title: str.title,
+              useForm: str.useForm
+            }
+          }).sortBy(['title']).value()
+          let localStrategy = _.remove(strategies, str => str.key === 'local')
+          return _.concat(localStrategy, strategies)
+        case 'all':
+
+          break
+        default:
+          return null
+      }
+    }
+  },
+  Mutation: {},
+  AuthenticationProvider: {
+    icon (ap, args) {
+      return fs.readFileAsync(path.join(wiki.ROOTPATH, `assets/svg/auth-icon-${ap.key}.svg`), 'utf8').catch(err => {
+        if (err.code === 'ENOENT') {
+          return null
+        }
+        throw err
+      })
+    }
+  }
+}
diff --git a/server/schemas/resolvers-comment.js b/server/schemas/resolvers-comment.js
new file mode 100644
index 00000000..fec565b3
--- /dev/null
+++ b/server/schemas/resolvers-comment.js
@@ -0,0 +1,42 @@
+
+/* global wiki */
+
+module.exports = {
+  Query: {
+    comments(obj, args, context, info) {
+      return wiki.db.Comment.findAll({ where: args })
+    }
+  },
+  Mutation: {
+    createComment(obj, args) {
+      return wiki.db.Comment.create({
+        content: args.content,
+        author: args.userId,
+        document: args.documentId
+      })
+    },
+    deleteComment(obj, args) {
+      return wiki.db.Comment.destroy({
+        where: {
+          id: args.id
+        },
+        limit: 1
+      })
+    },
+    modifyComment(obj, args) {
+      return wiki.db.Comment.update({
+        content: args.content
+      }, {
+        where: { id: args.id }
+      })
+    }
+  },
+  Comment: {
+    author(cm) {
+      return cm.getAuthor()
+    },
+    document(cm) {
+      return cm.getDocument()
+    }
+  }
+}
diff --git a/server/schemas/resolvers-document.js b/server/schemas/resolvers-document.js
new file mode 100644
index 00000000..41dc9160
--- /dev/null
+++ b/server/schemas/resolvers-document.js
@@ -0,0 +1,46 @@
+
+/* global wiki */
+
+module.exports = {
+  Query: {
+    documents(obj, args, context, info) {
+      return wiki.db.Document.findAll({ where: args })
+    }
+  },
+  Mutation: {
+    createDocument(obj, args) {
+      return wiki.db.Document.create(args)
+    },
+    deleteDocument(obj, args) {
+      return wiki.db.Document.destroy({
+        where: {
+          id: args.id
+        },
+        limit: 1
+      })
+    },
+    modifyDocument(obj, args) {
+      return wiki.db.Document.update({
+        title: args.title,
+        subtitle: args.subtitle
+      }, {
+        where: { id: args.id }
+      })
+    },
+    moveDocument(obj, args) {
+      return wiki.db.Document.update({
+        path: args.path
+      }, {
+        where: { id: args.id }
+      })
+    }
+  },
+  Document: {
+    comments(doc) {
+      return doc.getComments()
+    },
+    tags(doc) {
+      return doc.getTags()
+    }
+  }
+}
diff --git a/server/schemas/resolvers-file.js b/server/schemas/resolvers-file.js
new file mode 100644
index 00000000..c8913413
--- /dev/null
+++ b/server/schemas/resolvers-file.js
@@ -0,0 +1,51 @@
+
+/* global wiki */
+
+const gql = require('graphql')
+
+module.exports = {
+  Query: {
+    files(obj, args, context, info) {
+      return wiki.db.File.findAll({ where: args })
+    }
+  },
+  Mutation: {
+    uploadFile(obj, args) {
+      // todo
+      return wiki.db.File.create(args)
+    },
+    deleteFile(obj, args) {
+      return wiki.db.File.destroy({
+        where: {
+          id: args.id
+        },
+        limit: 1
+      })
+    },
+    renameFile(obj, args) {
+      return wiki.db.File.update({
+        filename: args.filename
+      }, {
+        where: { id: args.id }
+      })
+    },
+    moveFile(obj, args) {
+      return wiki.db.File.findById(args.fileId).then(fl => {
+        if (!fl) {
+          throw new gql.GraphQLError('Invalid File ID')
+        }
+        return wiki.db.Folder.findById(args.folderId).then(fld => {
+          if (!fld) {
+            throw new gql.GraphQLError('Invalid Folder ID')
+          }
+          return fl.setFolder(fld)
+        })
+      })
+    }
+  },
+  File: {
+    folder(fl) {
+      return fl.getFolder()
+    }
+  }
+}
diff --git a/server/schemas/resolvers-folder.js b/server/schemas/resolvers-folder.js
new file mode 100644
index 00000000..b7fc9a2b
--- /dev/null
+++ b/server/schemas/resolvers-folder.js
@@ -0,0 +1,35 @@
+
+/* global wiki */
+
+module.exports = {
+  Query: {
+    folders(obj, args, context, info) {
+      return wiki.db.Folder.findAll({ where: args })
+    }
+  },
+  Mutation: {
+    createFolder(obj, args) {
+      return wiki.db.Folder.create(args)
+    },
+    deleteGroup(obj, args) {
+      return wiki.db.Folder.destroy({
+        where: {
+          id: args.id
+        },
+        limit: 1
+      })
+    },
+    renameFolder(obj, args) {
+      return wiki.db.Folder.update({
+        name: args.name
+      }, {
+        where: { id: args.id }
+      })
+    }
+  },
+  Folder: {
+    files(grp) {
+      return grp.getFiles()
+    }
+  }
+}
diff --git a/server/schemas/resolvers-group.js b/server/schemas/resolvers-group.js
new file mode 100644
index 00000000..cc9b10b7
--- /dev/null
+++ b/server/schemas/resolvers-group.js
@@ -0,0 +1,63 @@
+
+/* global wiki */
+
+const gql = require('graphql')
+
+module.exports = {
+  Query: {
+    groups(obj, args, context, info) {
+      return wiki.db.Group.findAll({ where: args })
+    }
+  },
+  Mutation: {
+    assignUserToGroup(obj, args) {
+      return wiki.db.Group.findById(args.groupId).then(grp => {
+        if (!grp) {
+          throw new gql.GraphQLError('Invalid Group ID')
+        }
+        return wiki.db.User.findById(args.userId).then(usr => {
+          if (!usr) {
+            throw new gql.GraphQLError('Invalid User ID')
+          }
+          return grp.addUser(usr)
+        })
+      })
+    },
+    createGroup(obj, args) {
+      return wiki.db.Group.create(args)
+    },
+    deleteGroup(obj, args) {
+      return wiki.db.Group.destroy({
+        where: {
+          id: args.id
+        },
+        limit: 1
+      })
+    },
+    removeUserFromGroup(obj, args) {
+      return wiki.db.Group.findById(args.groupId).then(grp => {
+        if (!grp) {
+          throw new gql.GraphQLError('Invalid Group ID')
+        }
+        return wiki.db.User.findById(args.userId).then(usr => {
+          if (!usr) {
+            throw new gql.GraphQLError('Invalid User ID')
+          }
+          return grp.removeUser(usr)
+        })
+      })
+    },
+    renameGroup(obj, args) {
+      return wiki.db.Group.update({
+        name: args.name
+      }, {
+        where: { id: args.id }
+      })
+    }
+  },
+  Group: {
+    users(grp) {
+      return grp.getUsers()
+    }
+  }
+}
diff --git a/server/schemas/resolvers-right.js b/server/schemas/resolvers-right.js
new file mode 100644
index 00000000..3b286deb
--- /dev/null
+++ b/server/schemas/resolvers-right.js
@@ -0,0 +1,53 @@
+
+/* global wiki */
+
+const gql = require('graphql')
+
+module.exports = {
+  Query: {
+    rights(obj, args, context, info) {
+      return wiki.db.Right.findAll({ where: args })
+    }
+  },
+  Mutation: {
+    addRightToGroup(obj, args) {
+      return wiki.db.Group.findById(args.groupId).then(grp => {
+        if (!grp) {
+          throw new gql.GraphQLError('Invalid Group ID')
+        }
+        return wiki.db.Right.create({
+          path: args.path,
+          role: args.role,
+          exact: args.exact,
+          allow: args.allow,
+          group: grp
+        })
+      })
+    },
+    removeRightFromGroup(obj, args) {
+      return wiki.db.Right.destroy({
+        where: {
+          id: args.rightId
+        },
+        limit: 1
+      })
+    },
+    modifyRight(obj, args) {
+      return wiki.db.Right.update({
+        path: args.path,
+        role: args.role,
+        exact: args.exact,
+        allow: args.allow
+      }, {
+        where: {
+          id: args.id
+        }
+      })
+    }
+  },
+  Right: {
+    group(rt) {
+      return rt.getGroup()
+    }
+  }
+}
diff --git a/server/schemas/resolvers-setting.js b/server/schemas/resolvers-setting.js
new file mode 100644
index 00000000..dc0c4f9e
--- /dev/null
+++ b/server/schemas/resolvers-setting.js
@@ -0,0 +1,24 @@
+
+/* global wiki */
+
+const _ = require('lodash')
+
+module.exports = {
+  Query: {
+    settings(obj, args, context, info) {
+      return wiki.db.Setting.findAll({ where: args, raw: true }).then(entries => {
+        return _.map(entries, entry => {
+          entry.config = JSON.stringify(entry.config)
+          return entry
+        })
+      })
+    }
+  },
+  Mutation: {
+    setConfigEntry(obj, args) {
+      return wiki.db.Setting.update({
+        value: args.value
+      }, { where: { key: args.key } })
+    }
+  }
+}
diff --git a/server/schemas/resolvers-tag.js b/server/schemas/resolvers-tag.js
new file mode 100644
index 00000000..0aa3e89e
--- /dev/null
+++ b/server/schemas/resolvers-tag.js
@@ -0,0 +1,63 @@
+
+/* global wiki */
+
+const gql = require('graphql')
+
+module.exports = {
+  Query: {
+    tags(obj, args, context, info) {
+      return wiki.db.Tag.findAll({ where: args })
+    }
+  },
+  Mutation: {
+    assignTagToDocument(obj, args) {
+      return wiki.db.Tag.findById(args.tagId).then(tag => {
+        if (!tag) {
+          throw new gql.GraphQLError('Invalid Tag ID')
+        }
+        return wiki.db.Document.findById(args.documentId).then(doc => {
+          if (!doc) {
+            throw new gql.GraphQLError('Invalid Document ID')
+          }
+          return tag.addDocument(doc)
+        })
+      })
+    },
+    createTag(obj, args) {
+      return wiki.db.Tag.create(args)
+    },
+    deleteTag(obj, args) {
+      return wiki.db.Tag.destroy({
+        where: {
+          id: args.id
+        },
+        limit: 1
+      })
+    },
+    removeTagFromDocument(obj, args) {
+      return wiki.db.Tag.findById(args.tagId).then(tag => {
+        if (!tag) {
+          throw new gql.GraphQLError('Invalid Tag ID')
+        }
+        return wiki.db.Document.findById(args.documentId).then(doc => {
+          if (!doc) {
+            throw new gql.GraphQLError('Invalid Document ID')
+          }
+          return tag.removeDocument(doc)
+        })
+      })
+    },
+    renameTag(obj, args) {
+      return wiki.db.Group.update({
+        key: args.key
+      }, {
+        where: { id: args.id }
+      })
+    }
+  },
+  Tag: {
+    documents(tag) {
+      return tag.getDocuments()
+    }
+  }
+}
diff --git a/server/schemas/resolvers-translation.js b/server/schemas/resolvers-translation.js
new file mode 100644
index 00000000..aed8d57d
--- /dev/null
+++ b/server/schemas/resolvers-translation.js
@@ -0,0 +1,12 @@
+
+/* global wiki */
+
+module.exports = {
+  Query: {
+    translations (obj, args, context, info) {
+      return wiki.lang.getByNamespace(args.locale, args.namespace)
+    }
+  },
+  Mutation: {},
+  Translation: {}
+}
diff --git a/server/schemas/resolvers-user.js b/server/schemas/resolvers-user.js
new file mode 100644
index 00000000..90133707
--- /dev/null
+++ b/server/schemas/resolvers-user.js
@@ -0,0 +1,45 @@
+
+/* global wiki */
+
+module.exports = {
+  Query: {
+    users(obj, args, context, info) {
+      return wiki.db.User.findAll({ where: args })
+    }
+  },
+  Mutation: {
+    createUser(obj, args) {
+      return wiki.db.User.create(args)
+    },
+    deleteUser(obj, args) {
+      return wiki.db.User.destroy({
+        where: {
+          id: args.id
+        },
+        limit: 1
+      })
+    },
+    modifyUser(obj, args) {
+      return wiki.db.User.update({
+        email: args.email,
+        name: args.name,
+        provider: args.provider,
+        providerId: args.providerId,
+        role: args.role
+      }, {
+        where: { id: args.id }
+      })
+    },
+    resetUserPassword(obj, args) {
+      return false
+    },
+    setUserPassword(obj, args) {
+      return false
+    }
+  },
+  User: {
+    groups(usr) {
+      return usr.getGroups()
+    }
+  }
+}
diff --git a/server/schemas/scalar-date.js b/server/schemas/scalar-date.js
new file mode 100644
index 00000000..472312ad
--- /dev/null
+++ b/server/schemas/scalar-date.js
@@ -0,0 +1,21 @@
+
+const gql = require('graphql')
+
+module.exports = {
+  Date: new gql.GraphQLScalarType({
+    name: 'Date',
+    description: 'ISO date-time string at UTC',
+    parseValue(value) {
+      return new Date(value)
+    },
+    serialize(value) {
+      return value.toISOString()
+    },
+    parseLiteral(ast) {
+      if (ast.kind !== gql.Kind.STRING) {
+        throw new TypeError('Date value must be an string!')
+      }
+      return new Date(ast.value)
+    }
+  })
+}
diff --git a/server/schemas/types.graphql b/server/schemas/types.graphql
new file mode 100644
index 00000000..a47305b4
--- /dev/null
+++ b/server/schemas/types.graphql
@@ -0,0 +1,342 @@
+# SCALARS
+
+scalar Date
+
+# ENUMS
+
+enum UserRole {
+  guest
+  user
+  admin
+}
+
+enum FileType {
+  binary
+  image
+}
+
+enum RightRole {
+  read
+  write
+  manage
+}
+
+# INTERFACES
+
+interface Base {
+  id: Int!
+  createdAt: Date
+  updatedAt: Date
+}
+
+# TYPES
+
+type AuthenticationProvider {
+  key: String!
+  useForm: Boolean!
+  title: String!
+  props: [String]
+  icon: String
+  config: String
+}
+
+type Comment implements Base {
+  id: Int!
+  createdAt: Date
+  updatedAt: Date
+  content: String
+  document: Document!
+  author: User!
+}
+
+type Document implements Base {
+  id: Int!
+  createdAt: Date
+  updatedAt: Date
+  path: String!
+  title: String!
+  subtitle: String
+  parentPath: String
+  parentTitle: String
+  isDirectory: Boolean!
+  isEntry: Boolean!
+  searchContent: String
+  comments: [Comment]
+  tags: [Tag]
+}
+
+type File implements Base {
+  id: Int!
+  createdAt: Date
+  updatedAt: Date
+  category: FileType!
+  mime: String!
+  extra: String
+  filename: String!
+  basename: String!
+  filesize: Int!
+  folder: Folder
+}
+
+type Folder implements Base {
+  id: Int!
+  createdAt: Date
+  updatedAt: Date
+  name: String!
+  files: [File]
+}
+
+type Group implements Base {
+  id: Int!
+  createdAt: Date
+  updatedAt: Date
+  name: String!
+  users: [User]
+  rights: [Right]
+}
+
+type Right implements Base {
+  id: Int!
+  createdAt: Date
+  updatedAt: Date
+  path: String!
+  role: RightRole!
+  exact: Boolean!
+  allow: Boolean!
+  group: Group!
+}
+
+type SearchResult {
+  path: String
+  title: String
+  tags: [String]
+}
+
+type Setting implements Base {
+  id: Int!
+  createdAt: Date
+  updatedAt: Date
+  key: String!
+  config: String!
+}
+
+# Tags are attached to one or more documents
+type Tag implements Base {
+  id: Int!
+  createdAt: Date
+  updatedAt: Date
+  key: String!
+  documents: [Document]
+}
+
+type Translation {
+  key: String!
+  value: String!
+}
+
+# A User
+type User implements Base {
+  id: Int!
+  createdAt: Date
+  updatedAt: Date
+  email: String!
+  provider: String!
+  providerId: String
+  name: String
+  role: UserRole!
+  groups: [Group]
+}
+
+type OperationResult {
+  succeded: Boolean!
+  message: String
+}
+
+# Query (Read)
+type Query {
+  authentication(mode: String!): [AuthenticationProvider]
+  comments(id: Int): [Comment]
+  documents(id: Int, path: String): [Document]
+  files(id: Int): [File]
+  folders(id: Int, name: String): [Folder]
+  groups(id: Int, name: String): [Group]
+  rights(id: Int): [Right]
+  search(q: String, tags: [String]): [SearchResult]
+  settings(key: String): [Setting]
+  tags(key: String): [Tag]
+  translations(locale: String!, namespace: String!): [Translation]
+  users(id: Int, email: String, provider: String, providerId: String, role: UserRole): [User]
+}
+
+# Mutations (Create, Update, Delete)
+type Mutation {
+  addRightToGroup(
+    groupId: Int!
+    path: String!
+    role: RightRole!
+    exact: Boolean!
+    allow: Boolean!
+  ): Right
+
+  assignTagToDocument(
+    tagId: Int!
+    documentId: Int!
+  ): OperationResult
+
+  assignUserToGroup(
+    userId: Int!
+    groupId: Int!
+  ): OperationResult
+
+  createComment(
+    userId: Int!
+    documentId: Int!
+    content: String!
+  ): Comment
+
+  createDocument(
+    path: String!
+    title: String!
+    subtitle: String
+  ): Document
+
+  createFolder(
+    name: String!
+  ): Folder
+
+  createGroup(
+    name: String!
+  ): Group
+
+  createTag(
+    name: String!
+  ): Tag
+
+  createUser(
+    email: String!
+    name: String
+    passwordRaw: String
+    provider: String!
+    providerId: String
+    role: UserRole!
+  ): User
+
+  deleteComment(
+    id: Int!
+  ): OperationResult
+
+  deleteDocument(
+    id: Int!
+  ): OperationResult
+
+  deleteFile(
+    id: Int!
+  ): OperationResult
+
+  deleteFolder(
+    id: Int!
+  ): OperationResult
+
+  deleteGroup(
+    id: Int!
+  ): OperationResult
+
+  deleteTag(
+    id: Int!
+  ): OperationResult
+
+  deleteUser(
+    id: Int!
+  ): OperationResult
+
+  modifyComment(
+    id: Int!
+    content: String!
+  ): Document
+
+  modifyDocument(
+    id: Int!
+    title: String
+    subtitle: String
+  ): Document
+
+  modifyUser(
+    id: Int!
+    email: String
+    name: String
+    provider: String
+    providerId: String
+    role: UserRole
+  ): User
+
+  modifyRight(
+    id: Int!
+    path: String
+    role: RightRole
+    exact: Boolean
+    allow: Boolean
+  ): Right
+
+  moveDocument(
+    id: Int!
+    path: String!
+  ): OperationResult
+
+  moveFile(
+    id: Int!
+    folderId: Int!
+  ): OperationResult
+
+  renameFile(
+    id: Int!
+    name: String!
+  ): OperationResult
+
+  renameFolder(
+    id: Int!
+    name: String!
+  ): OperationResult
+
+  renameGroup(
+    id: Int!
+    name: String!
+  ): OperationResult
+
+  renameTag(
+    id: Int!
+    key: String!
+  ): OperationResult
+
+  removeTagFromDocument(
+    tagId: Int!
+    documentId: Int!
+  ): OperationResult
+
+  removeRightFromGroup(
+    rightId: Int!
+  ): OperationResult
+
+  removeUserFromGroup(
+    userId: Int!
+    groupId: Int!
+  ): OperationResult
+
+  resetUserPassword(
+    id: Int!
+  ): OperationResult
+
+  setConfigEntry(
+    key: String!
+    value: String!
+  ): OperationResult
+
+  setUserPassword(
+    id: Int!
+    passwordRaw: String!
+  ): OperationResult
+
+  uploadFile(
+    category: FileType!
+    filename: String!
+  ): File
+}
diff --git a/server/views/auth/login.pug b/server/views/auth/login.pug
index ad860349..44ebc019 100644
--- a/server/views/auth/login.pug
+++ b/server/views/auth/login.pug
@@ -1,75 +1,6 @@
-doctype html
-html(data-logic='login')
-  head
-    meta(http-equiv='X-UA-Compatible', content='IE=edge')
-    meta(charset='UTF-8')
-    meta(name='viewport', content='width=device-width, initial-scale=1')
-    meta(name='theme-color', content='#009688')
-    meta(name='msapplication-TileColor', content='#009688')
-    meta(name='msapplication-TileImage', content='/favicons/ms-icon-144x144.png')
-    title= appconfig.title
-
-    // Favicon
-    each favsize in [57, 60, 72, 76, 114, 120, 144, 152, 180]
-      link(rel='apple-touch-icon', sizes=favsize + 'x' + favsize, href='/favicons/apple-icon-' + favsize + 'x' + favsize + '.png')
-    link(rel='icon', type='image/png', sizes='192x192', href='/favicons/android-icon-192x192.png')
-    each favsize in [32, 96, 16]
-      link(rel='icon', type='image/png', sizes=favsize + 'x' + favsize, href='/favicons/favicon-' + favsize + 'x' + favsize + '.png')
-    link(rel='manifest', href='/manifest.json')
-
-    // JS / CSS
-    script(type='text/javascript', src=appconfig.host + '/js/vendor.js')
-    script(type='text/javascript', src=appconfig.host + '/js/app.js')
+extends ../master.pug
 
+block body
   body
-    #bg
-      each bg in _.sampleSize([1, 2, 3],3)
-        div(style='background-image:url(/images/bg_' + bg + '.jpg);')
-    #root
-      h1= appconfig.title
-      h2= t('auth:loginrequired')
-      if appflash.length > 0
-        h3
-          i.icon-warning-outline
-          = appflash[0].title
-        h4= appflash[0].message
-      if appconfig.auth.local.enabled
-        form(method='post', action='/login')
-          input#login-user(type='text', name='email', placeholder=t('auth:fields.emailuser'))
-          input#login-pass(type='password', name='password', placeholder=t('auth:fields.password'))
-          button(type='submit')= t('auth:actions.login')
-      if appconfig.authStrategies.socialEnabled
-        #social
-          if appconfig.auth.local.enabled
-            span= t('auth:loginusingalt')
-          else
-            span= t('auth:loginusing')
-          if appconfig.auth.microsoft && appconfig.auth.microsoft.enabled
-            button.ms(onclick='window.location.assign("/login/ms")')
-              i.icon-windows2
-              span= t('auth:providers.windowslive')
-          if appconfig.auth.azure && appconfig.auth.azure.enabled
-            button.ms(onclick='window.location.assign("/login/azure")')
-              i.icon-windows2
-              span= t('auth:providers.azure')
-          if appconfig.auth.google && appconfig.auth.google.enabled
-            button.google(onclick='window.location.assign("/login/google")')
-              i.icon-google
-              span= t('auth:providers.google')
-          if appconfig.auth.facebook && appconfig.auth.facebook.enabled
-            button.facebook(onclick='window.location.assign("/login/facebook")')
-              i.icon-facebook
-              span= t('auth:providers.facebook')
-          if appconfig.auth.github && appconfig.auth.github.enabled
-            button.github(onclick='window.location.assign("/login/github")')
-              i.icon-github
-              span= t('auth:providers.github')
-          if appconfig.auth.slack && appconfig.auth.slack.enabled
-            button.slack(onclick='window.location.assign("/login/slack")')
-              i.icon-slack
-              span= t('auth:providers.slack')
-    #copyright
-      = t('footer.poweredby') + ' '
-      a.icon(href='https://github.com/Requarks/wiki')
-        i.icon-github
-      a(href='https://wiki.requarks.io/') Wiki.js
+    #app.is-fullscreen
+      login
diff --git a/server/views/configure/index.pug b/server/views/configure/index.pug
index d6c1f62a..aa268c77 100644
--- a/server/views/configure/index.pug
+++ b/server/views/configure/index.pug
@@ -1,31 +1,9 @@
-doctype html
-html(data-logic='configure')
-  head
-    meta(http-equiv='X-UA-Compatible', content='IE=edge')
-    meta(charset='UTF-8')
-    title Wiki.js | Configure
-
-    // Favicon
-    each favsize in [32, 96, 16]
-      link(rel='icon', type='image/png', sizes=favsize + 'x' + favsize, href='/favicons/favicon-' + favsize + 'x' + favsize + '.png')
-
-    // JS / CSS
-    script(type='text/javascript').
-      var appconfig = !{JSON.stringify(conf)};
-      var runmode = !{JSON.stringify(runmode)};
-    script(type='text/javascript', src='/js/vendor.js')
-    script(type='text/javascript', src='/js/configure.js')
+extends ../master.pug
 
+block body
   body
-    #root
-      #header-container
-        nav.nav#header
-          .nav-left
-            a.nav-item
-              h1
-                i.icon-layers
-                | Wiki.js
-      main
+    #app.config-manager
+      config-manager(inline-template)
         .container
           transition(name='tst-welcome')
             .welcome(v-if='state === "welcome" || state === "restart"')
@@ -44,10 +22,22 @@ html(data-logic='configure')
                   i(v-if='loading')
                 .panel-content.is-text
                   p This installation wizard will guide you through the steps needed to get your wiki up and running in no time!
-                  p Detailed information about installation and usage can be found on the #[a(href='https://docs.wiki.requarks.io/') official documentation site]. #[br] Should you have any question or would like to report something that doesn't look right, feel free to create a new issue on the #[a(href='https://github.com/Requarks/wiki/issues') GitHub project].
+                  p Detailed information about installation and usage can be found on the #[a(href='https://wiki.requarks.io/docs') official documentation site]. #[br] Should you have any question or would like to report something that doesn't look right, feel free to create a new issue on the #[a(href='https://github.com/Requarks/wiki/issues') GitHub project].
+                .panel-content.form-sections
+                  section
+                    p #[i.nc-icon-outline.tech_cd-reader] You are about to install Wiki.js #[strong= packageObj.version].
+                  section
+                    p.control.is-fullwidth
+                      input#ipt-telemetry(type='checkbox', v-model='conf.telemetry', name='ipt-telemetry')
+                      label.label(for='ipt-telemetry') Enable telemetry
+                      span.desc Help Wiki.js developers improve this app with anonymized #[a(href='https://wiki.requarks.io/docs/telemetry') telemetry].
+                    p.control.is-fullwidth
+                      input#ipt-upgrade(type='checkbox', v-model='conf.upgrade', name='ipt-upgrade')
+                      label.label(for='ipt-upgrade') Upgrade from Wiki.js 1.x
+                      span.desc Check this box if you are upgrading from Wiki.js 1.x and wish to migrate your existing data.
                 .panel-footer
                   .progress-bar: div(v-bind:style='{width: currentProgress}')
-                  button.button.is-light-blue(v-on:click='proceedToSyscheck', v-bind:disabled='loading') Start
+                  button.button.is-small.is-light-blue(v-on:click='proceedToSyscheck', v-bind:disabled='loading') Start
 
             //- ==============================================
             //- SYSTEM CHECK
@@ -69,9 +59,10 @@ html(data-logic='configure')
                   p(v-if='!loading && !syscheck.ok') #[i.icon-square-cross] Error: {{ syscheck.error }}
                 .panel-footer
                   .progress-bar: div(v-bind:style='{width: currentProgress}')
-                  button.button.is-light-blue.is-outlined(v-on:click='proceedToWelcome', v-bind:disabled='loading') Back
-                  button.button.is-teal(v-on:click='proceedToSyscheck', v-if='!loading && !syscheck.ok') Check Again
-                  button.button.is-light-blue(v-on:click='proceedToGeneral', v-if='loading || syscheck.ok', v-bind:disabled='loading') Continue
+                  button.button.is-small.is-light-blue.is-outlined(v-on:click='proceedToWelcome', v-bind:disabled='loading') Back
+                  button.button.is-small.is-teal(v-on:click='proceedToSyscheck', v-if='!loading && !syscheck.ok') Check Again
+                  button.button.is-small.is-red.is-outlined(v-on:click='proceedToGeneral', v-if='!loading && !syscheck.ok') Continue Anyway
+                  button.button.is-small.is-light-blue(v-on:click='proceedToGeneral', v-if='loading || syscheck.ok', v-bind:disabled='loading') Continue
 
             //- ==============================================
             //- GENERAL
@@ -92,20 +83,24 @@ html(data-logic='configure')
                     p.control.is-fullwidth
                       label.label Host
                       input(type='text', placeholder='http://', v-model='conf.host', data-vv-scope='general', name='ipt-host', v-validate='{ required: true, min: 4 }')
-                      span.desc The full URL to your wiki, without the trailing slash. E.g.: http://wiki.domain.com. Note that sub-folders are #[u not supported].
-                  if !runmode.staticPort
-                    section
-                      p.control
-                        label.label Port
-                        input(type='text', placeholder='e.g. 80', v-model.number='conf.port', data-vv-scope='general', name='ipt-port', v-validate='{ required: true }')
-                        span.desc The port on which Wiki.js will listen to. Usually port 80 if connecting directly, or a random port (e.g. 3000) if using a web server in front of it.<br>Set <strong>$(PORT)</strong> to use PORT environment variable.
+                      span.desc The full URL to your wiki, without the trailing slash, e.g.: http://wiki.domain.com. Make sure to include the port if different than 80/443.
+                  section
+                    p.control
+                      label.label Port
+                      input(type='text', placeholder='e.g. 80', v-model.number='conf.port', data-vv-scope='general', name='ipt-port', v-validate='{ required: true }')
+                      span.desc The port on which Wiki.js will listen to. Usually port 80 if connecting directly, or a random port (e.g. 3000) if using a web server in front of it.<br>Set <strong>$(PORT)</strong> to use PORT environment variable.
                   section
                     p.control
                       label.label Site UI Language
                       select(v-model='conf.lang')
-                        each lg in langs
+                        each lg in data.langs
                           option(value=lg.id)= lg.name
                       span.desc The language in which navigation, help and other UI elements will be displayed.
+                  section
+                    p.control.is-fullwidth
+                      label.label Local Repository Path
+                      input(type='text', placeholder='e.g. ./repo', v-model='conf.pathRepo', data-vv-scope='general', name='ipt-repopath', v-validate='{ required: true, min: 2 }')
+                      span.desc The path where the local git repository will be created, used to store content in markdown files and uploads.#[br] #[strong It is recommended to leave the default value].
                   section
                     p.control.is-fullwidth
                       input#ipt-public(type='checkbox', v-model='conf.public', data-vv-scope='general', name='ipt-public')
@@ -113,8 +108,8 @@ html(data-logic='configure')
                       span.desc Should the site be accessible (read only) without login.
                 .panel-footer
                   .progress-bar: div(v-bind:style='{width: currentProgress}')
-                  button.button.is-light-blue.is-outlined(v-on:click='proceedToSyscheck', v-bind:disabled='loading') Back
-                  button.button.is-light-blue(v-on:click='proceedToConsiderations', v-bind:disabled='loading || errors.any("general")') Continue
+                  button.button.is-small.is-light-blue.is-outlined(v-on:click='proceedToSyscheck', v-bind:disabled='loading') Back
+                  button.button.is-small.is-light-blue(v-on:click='proceedToConsiderations', v-bind:disabled='loading || errors.any("general")') Continue
 
             //- ==============================================
             //- CONSIDERATIONS
@@ -134,88 +129,18 @@ html(data-logic='configure')
                       li - Do not rewrite URLs after the domain. This can cause unexpected issues in Wiki.js navigation.
                       li - Do not remove or alter the client IP when proxying the requests. This can cause the authentication brute force protection to engage unexpectedly.
                   template(v-if='considerations.https')
-                    h3 The site will not be using HTTPS? #[i.icon-warning-outline.animated.fadeOut.infinite]
+                    h3 The site will not be using HTTPS? #[i.nc-icon-outline.ui-3_alert.animated.fadeOut.infinite]
                     p The host URL you specified is not HTTPS. It is highly recommended to use HTTPS. You must use a web server / proxy (e.g. nginx / apache / IIS) in front of Wiki.js to use HTTPS. Wiki.js does not provide HTTPS handling by itself.
                   template(v-if='considerations.port')
                     h3 You are using a non-standard port.
                     p If you are not planning on using a web server / proxy in front of Wiki.js, be aware that users will need to specify the port when accessing the wiki. Make sure this is the intended behavior. Otherwise set a standard HTTP port such as 80.
                   template(v-if='considerations.localhost')
-                    h3 Are you sure you want to use localhost as the host base URL? #[i.icon-warning-outline.animated.fadeOut.infinite]
+                    h3 Are you sure you want to use localhost as the host base URL? #[i.nc-icon-outline.ui-3_alert.animated.fadeOut.infinite]
                     p The host URL you specified is localhost. Unless you are a developer running Wiki.js locally on your machine, this is not recommended!
                 .panel-footer
                   .progress-bar: div(v-bind:style='{width: currentProgress}')
-                  button.button.is-light-blue.is-outlined(v-on:click='proceedToGeneral', v-bind:disabled='loading') Back
-                  button.button.is-light-blue(v-on:click='proceedToDb', v-bind:disabled='loading') Continue
-
-            //- ==============================================
-            //- DATABASE
-            //- ==============================================
-
-            template(v-else-if='state === "db"')
-              .panel
-                h2.panel-title.is-featured
-                  span Database
-                  i(v-if='loading')
-                .panel-content.is-text
-                  p Wiki.js stores administrative data such as users, permissions and assets metadata in a MongoDB database. Article contents and uploads are <u>not</u> stored in the DB. Instead, they are stored on-disk and synced automatically with a remote git repository of your choice.
-                .panel-content.form-sections
-                  section
-                    p.control.is-fullwidth
-                      label.label MongoDB Connection String
-                      input(type='text', placeholder='e.g. mongodb://localhost:27017/wiki', v-model='conf.db', data-vv-scope='db', name='ipt-db', v-validate='{ required: true, min: 3 }')
-                      span.desc The connection string to your MongoDB server. Leave the default localhost value if MongoDB is installed on the same server.<br />You can also specify an environment variable as the connection string, e.g. $(MONGO_URI).
-                .panel-footer
-                  .progress-bar: div(v-bind:style='{width: currentProgress}')
-                  button.button.is-light-blue.is-outlined(v-on:click='proceedToConsiderations', v-bind:disabled='loading') Back
-                  button.button.is-light-blue(v-on:click='proceedToDbcheck', v-bind:disabled='loading || errors.any("db")') Connect
-
-            //- ==============================================
-            //- DATABASE CHECK
-            //- ==============================================
-
-            template(v-else-if='state === "dbcheck"')
-              .panel
-                h2.panel-title.is-featured
-                  span Database Check
-                  i(v-if='loading')
-                .panel-content.is-text
-                  p(v-if='loading') #[i.icon-loader.animated.rotateIn.infinite] Testing the connection to MongoDB...
-                  p(v-if='!loading && dbcheck.ok')
-                    i.icon-check
-                    strong  Connected successfully!
-                  p(v-if='!loading && !dbcheck.ok') #[i.icon-square-cross] Error: {{ dbcheck.error }}
-                .panel-footer
-                  .progress-bar: div(v-bind:style='{width: currentProgress}')
-                  button.button.is-light-blue.is-outlined(v-on:click='proceedToDb', v-bind:disabled='loading') Back
-                  button.button.is-teal(v-on:click='proceedToDbcheck', v-if='!loading && !dbcheck.ok') Try Again
-                  button.button.is-light-blue(v-on:click='proceedToPaths', v-if='loading || dbcheck.ok', v-bind:disabled='loading') Continue
-
-            //- ==============================================
-            //- PATHS
-            //- ==============================================
-
-            template(v-else-if='state === "paths"')
-              .panel
-                h2.panel-title.is-featured
-                  span Paths
-                  i(v-if='loading')
-                .panel-content.is-text
-                  p It is recommended to leave the default values.
-                .panel-content.form-sections
-                  section
-                    p.control.is-fullwidth
-                      label.label Local Data Path
-                      input(type='text', placeholder='e.g. ./data', v-model='conf.pathData', data-vv-scope='paths', name='ipt-datapath', v-validate='{ required: true, min: 2 }')
-                      span.desc The path where cache (processed content, thumbnails, search index, etc.) will be stored on disk.
-                  section
-                    p.control.is-fullwidth
-                      label.label Local Repository Path
-                      input(type='text', placeholder='e.g. ./repo', v-model='conf.pathRepo', data-vv-scope='paths', name='ipt-repopath', v-validate='{ required: true, min: 2 }')
-                      span.desc The path where the local git repository will be created, used to store content in markdown files and uploads.
-                .panel-footer
-                  .progress-bar: div(v-bind:style='{width: currentProgress}')
-                  button.button.is-light-blue.is-outlined(v-on:click='proceedToDb', v-bind:disabled='loading') Back
-                  button.button.is-light-blue(v-on:click='proceedToGit', v-bind:disabled='loading || errors.any("paths")') Continue
+                  button.button.is-small.is-light-blue.is-outlined(v-on:click='proceedToGeneral', v-bind:disabled='loading') Back
+                  button.button.is-small.is-light-blue(v-on:click='proceedToGit', v-bind:disabled='loading') Continue
 
             //- ==============================================
             //- GIT
@@ -279,9 +204,9 @@ html(data-logic='configure')
                         span.desc The default/fallback email to use when creating commits to the git repository.
                 .panel-footer
                   .progress-bar: div(v-bind:style='{width: currentProgress}')
-                  button.button.is-light-blue.is-outlined(v-on:click='proceedToPaths', v-bind:disabled='loading') Back
-                  button.button.is-light-blue.is-outlined(v-on:click='conf.gitUseRemote = false; proceedToGitCheck()', v-bind:disabled='loading') Skip this step
-                  button.button.is-light-blue(v-on:click='conf.gitUseRemote = true; proceedToGitCheck()', v-bind:disabled='loading || errors.any("git")') Continue
+                  button.button.is-small.is-light-blue.is-outlined(v-on:click='proceedToGeneral', v-bind:disabled='loading') Back
+                  button.button.is-small.is-light-blue.is-outlined(v-on:click='conf.gitUseRemote = false; proceedToGitCheck()', v-bind:disabled='loading') Skip this step
+                  button.button.is-small.is-light-blue(v-on:click='conf.gitUseRemote = true; proceedToGitCheck()', v-bind:disabled='loading || errors.any("git")') Continue
             
             //- ==============================================
             //- GIT CHECK
@@ -303,9 +228,9 @@ html(data-logic='configure')
                   p(v-if='!loading && !gitcheck.ok') #[i.icon-square-cross] Error: {{ gitcheck.error }}
                 .panel-footer
                   .progress-bar: div(v-bind:style='{width: currentProgress}')
-                  button.button.is-light-blue.is-outlined(v-on:click='proceedToGit', v-bind:disabled='loading') Back
-                  button.button.is-teal(v-on:click='proceedToGitCheck', v-if='!loading && !gitcheck.ok') Try Again
-                  button.button.is-light-blue(v-on:click='proceedToAdmin', v-if='loading || gitcheck.ok', v-bind:disabled='loading') Continue
+                  button.button.is-small.is-light-blue.is-outlined(v-on:click='proceedToGit', v-bind:disabled='loading') Back
+                  button.button.is-small.is-teal(v-on:click='proceedToGitCheck', v-if='!loading && !gitcheck.ok') Try Again
+                  button.button.is-small.is-light-blue(v-on:click='proceedToAdmin', v-if='loading || gitcheck.ok', v-bind:disabled='loading') Continue
 
             //- ==============================================
             //- ADMINISTRATOR ACCOUNT
@@ -337,8 +262,8 @@ html(data-logic='configure')
                         span.desc Verify your password again.
                 .panel-footer
                   .progress-bar: div(v-bind:style='{width: currentProgress}')
-                  button.button.is-light-blue.is-outlined(v-on:click='proceedToGit', v-bind:disabled='loading') Back
-                  button.button.is-light-blue(v-on:click='proceedToFinal', v-bind:disabled='loading || errors.any("admin")') Continue
+                  button.button.is-small.is-light-blue.is-outlined(v-on:click='proceedToGit', v-bind:disabled='loading') Back
+                  button.button.is-small.is-light-blue(v-on:click='proceedToFinal', v-bind:disabled='loading || errors.any("admin")') Continue
 
             //- ==============================================
             //- FINAL
@@ -359,9 +284,9 @@ html(data-logic='configure')
                   p(v-if='!loading && !final.ok') #[i.icon-square-cross] Error: {{ final.error }}
                 .panel-footer
                   .progress-bar: div(v-bind:style='{width: currentProgress}')
-                  button.button.is-light-blue.is-outlined(v-on:click='proceedToAdmin', v-bind:disabled='loading') Back
-                  button.button.is-teal(v-on:click='proceedToFinal', v-if='!loading && !final.ok') Try Again
-                  button.button.is-green(v-on:click='finish', v-if='loading || final.ok', v-bind:disabled='loading') Start
+                  button.button.is-small.is-light-blue.is-outlined(v-on:click='proceedToAdmin', v-bind:disabled='loading') Back
+                  button.button.is-small.is-teal(v-on:click='proceedToFinal', v-if='!loading && !final.ok') Try Again
+                  button.button.is-small.is-green(v-on:click='finish', v-if='loading || final.ok', v-bind:disabled='loading') Start
 
             //- ==============================================
             //- RESTART
@@ -376,11 +301,4 @@ html(data-logic='configure')
                   p #[i.icon-loader.animated.rotateIn.infinite] Restarting Wiki.js in normal mode...
                   p You'll automatically be redirected to the homepage when ready. This usually takes about 30 seconds.
                 .panel-footer
-                  button.button.is-green(disabled='disabled') Start
-
-      footer.footer
-        span
-          | Powered by 
-          a(href='https://github.com/Requarks/wiki') Wiki.js
-          | .
-    block outside
+                  button.button.is-small.is-green(disabled='disabled') Start
diff --git a/server/views/error.pug b/server/views/error.pug
index 3ef6c43f..51b53efe 100644
--- a/server/views/error.pug
+++ b/server/views/error.pug
@@ -1,32 +1,12 @@
-doctype html
-html(data-logic='error')
-  head
-    meta(http-equiv='X-UA-Compatible', content='IE=edge')
-    meta(charset='UTF-8')
-    meta(name='viewport', content='width=device-width, initial-scale=1')
-    meta(name='theme-color', content='#009688')
-    meta(name='msapplication-TileColor', content='#009688')
-    meta(name='msapplication-TileImage', content=appconfig.host + '/favicons/ms-icon-144x144.png')
-    title= appconfig.title
-
-    // Favicon
-    each favsize in [57, 60, 72, 76, 114, 120, 144, 152, 180]
-      link(rel='apple-touch-icon', sizes=favsize + 'x' + favsize, href=appconfig.host + '/favicons/apple-icon-' + favsize + 'x' + favsize + '.png')
-    link(rel='icon', type='image/png', sizes='192x192', href=appconfig.host + '/favicons/android-icon-192x192.png')
-    each favsize in [32, 96, 16]
-      link(rel='icon', type='image/png', sizes=favsize + 'x' + favsize, href=appconfig.host + '/favicons/favicon-' + favsize + 'x' + favsize + '.png')
-    link(rel='manifest', href=appconfig.host + '/manifest.json')
-
-    // JS / CSS
-    script(type='text/javascript', src=appconfig.host + '/js/vendor.js')
-    script(type='text/javascript', src=appconfig.host + '/js/app.js')
+extends ./master.pug
 
+block body
   body(class='is-error')
     .container
-      a(href='/'): img(src=appconfig.host + '/images/logo.png')
+      a(href='/'): img(src=config.site.path + '/images/logo.png')
       h1= message
       h2= t('errors:generic')
-      a.button.is-amber.is-inverted.is-featured(href=appconfig.host + '/')= t('errors:actions.gohome')
+      a.button.is-amber.is-inverted.is-featured(href=config.site.path+ '/')= t('errors:actions.gohome')
 
       if error.stack
         h3= t('errors:debugmsg')
diff --git a/server/views/layout.pug b/server/views/layout.pug
index 36c75734..1d704f7e 100644
--- a/server/views/layout.pug
+++ b/server/views/layout.pug
@@ -1,35 +1,8 @@
-doctype html
-html
-  head
-    meta(http-equiv='X-UA-Compatible', content='IE=edge')
-    meta(charset='UTF-8')
-    meta(name='viewport', content='width=device-width, initial-scale=1')
-    meta(name='theme-color', content='#009688')
-    meta(name='msapplication-TileColor', content='#009688')
-    meta(name='msapplication-TileImage', content=appconfig.host + '/favicons/ms-icon-144x144.png')
-    title= appconfig.title
+extends ./master.pug
 
-    //- Favicon
-    each favsize in [57, 60, 72, 76, 114, 120, 144, 152, 180]
-      link(rel='apple-touch-icon', sizes=favsize + 'x' + favsize, href=appconfig.host + '/favicons/apple-icon-' + favsize + 'x' + favsize + '.png')
-    link(rel='icon', type='image/png', sizes='192x192', href=appconfig.host + '/favicons/android-icon-192x192.png')
-    each favsize in [32, 96, 16]
-      link(rel='icon', type='image/png', sizes=favsize + 'x' + favsize, href=appconfig.host + '/favicons/favicon-' + favsize + 'x' + favsize + '.png')
-    link(rel='manifest', href=appconfig.host + '/manifest.json')
-
-    //- Site Lang
-    script.
-      var siteLang = '!{appconfig.lang}';
-      var siteRoot = '!{appconfig.host}';
-
-    //- JS / CSS
-    script(type='text/javascript', src=appconfig.host + '/js/vendor.js')
-    script(type='text/javascript', src=appconfig.host + '/js/app.js')
-
-    block head
-
-  body(class={ 'rtl': appconfig.langRtl })
-    #root.has-stickynav(class=['is-primary-' + appconfig.theme.primary, 'is-alternate-' + appconfig.theme.alt])
+block body
+  body
+    #app.has-stickynav(class=['is-primary-' + appconfig.theme.primary, 'is-alternate-' + appconfig.theme.alt])
       include ./common/header.pug
       alert
       main
diff --git a/server/views/master.pug b/server/views/master.pug
new file mode 100644
index 00000000..dc45732a
--- /dev/null
+++ b/server/views/master.pug
@@ -0,0 +1,30 @@
+doctype html
+html
+  head
+    meta(http-equiv='X-UA-Compatible', content='IE=edge')
+    meta(charset='UTF-8')
+    meta(name='viewport', content='width=device-width, initial-scale=1')
+    meta(name='theme-color', content='#009688')
+    meta(name='msapplication-TileColor', content='#009688')
+    meta(name='msapplication-TileImage', content=config.site.path + '/favicons/ms-icon-144x144.png')
+    title= config.site.title
+
+    //- Favicon
+    each favsize in [57, 60, 72, 76, 114, 120, 144, 152, 180]
+      link(rel='apple-touch-icon', sizes=favsize + 'x' + favsize, href=config.site.path + '/favicons/apple-icon-' + favsize + 'x' + favsize + '.png')
+    link(rel='icon', type='image/png', sizes='192x192', href=config.site.path + '/favicons/android-icon-192x192.png')
+    each favsize in [32, 96, 16]
+      link(rel='icon', type='image/png', sizes=favsize + 'x' + favsize, href=config.site.path + '/favicons/favicon-' + favsize + 'x' + favsize + '.png')
+    link(rel='manifest', href=config.site.path + '/manifest.json')
+
+    //- Site Lang
+    script.
+      var siteConfig = !{JSON.stringify(config.site)}
+
+    //- JS / CSS
+    script(type='text/javascript', src=config.site.path + '/js/libs.js')
+    script(type='text/javascript', src=config.site.path + '/js/app.js')
+
+    block head
+
+  block body
diff --git a/server/worker.js b/server/worker.js
new file mode 100644
index 00000000..6ca90eba
--- /dev/null
+++ b/server/worker.js
@@ -0,0 +1,67 @@
+/* global wiki */
+
+const Promise = require('bluebird')
+
+module.exports = Promise.join(
+  wiki.db.onReady,
+  wiki.configSvc.loadFromDb(['features', 'git', 'logging', 'site', 'uploads'])
+).then(() => {
+  const path = require('path')
+
+  wiki.REPOPATH = path.resolve(wiki.ROOTPATH, wiki.config.paths.repo)
+  wiki.DATAPATH = path.resolve(wiki.ROOTPATH, wiki.config.paths.data)
+  wiki.UPLTEMPPATH = path.join(wiki.DATAPATH, 'temp-upload')
+
+  // ----------------------------------------
+  // Load global modules
+  // ----------------------------------------
+
+  // wiki.upl = require('./modules/uploads-agent').init()
+  // wiki.git = require('./modules/git').init()
+  // wiki.entries = require('./modules/entries').init()
+  wiki.lang = require('i18next')
+  wiki.mark = require('./modules/markdown')
+
+  // ----------------------------------------
+  // Localization Engine
+  // ----------------------------------------
+
+  const i18nBackend = require('i18next-node-fs-backend')
+  wiki.lang.use(i18nBackend).init({
+    load: 'languageOnly',
+    ns: ['common', 'admin', 'auth', 'errors', 'git'],
+    defaultNS: 'common',
+    saveMissing: false,
+    preload: [wiki.config.lang],
+    lng: wiki.config.lang,
+    fallbackLng: 'en',
+    backend: {
+      loadPath: path.join(wiki.SERVERPATH, 'locales/{{lng}}/{{ns}}.json')
+    }
+  })
+
+  // ----------------------------------------
+  // Start Queues
+  // ----------------------------------------
+
+  const Bull = require('bull')
+  const autoload = require('auto-load')
+
+  let queues = autoload(path.join(wiki.SERVERPATH, 'queues'))
+
+  for (let queueName in queues) {
+    new Bull(queueName, {
+      prefix: `q-${wiki.config.ha.nodeuid}`,
+      redis: wiki.config.redis
+    }).process(queues[queueName])
+  }
+
+  // ----------------------------------------
+  // Shutdown gracefully
+  // ----------------------------------------
+
+  process.on('disconnect', () => {
+    wiki.logger.warn('Lost connection to Master. Exiting...')
+    process.exit()
+  })
+})
diff --git a/themes/default/theme.yml b/themes/default/theme.yml
new file mode 100644
index 00000000..e5c0a6d8
--- /dev/null
+++ b/themes/default/theme.yml
@@ -0,0 +1,28 @@
+name: Default
+author: Nicolas Giard
+site: https://wiki.requarks.io/
+version: 1.0.0
+requirements:
+  minimum: '>= 2.0.0'
+  maximum: '< 3.0.0'
+fields:
+  primary:
+    title: Primary Color
+    description: Used for top navigation bar, headers, links, etc.
+    type: color
+    default: indigo
+  alt:
+    title: Alternate Color
+    description: Used for the sidebar (in a darker tone)
+    type: color
+    default: blue-grey
+  codeDark:
+    title: Code Blocks - Use Dark Theme
+    description: todo
+    type: boolean
+    default: true
+  codeColorize:
+    title: Code Blocks - Colorize syntax
+    description: todo
+    type: boolean
+    default: true
\ No newline at end of file
diff --git a/themes/default/thumbnail.png b/themes/default/thumbnail.png
new file mode 100644
index 00000000..489e3f83
Binary files /dev/null and b/themes/default/thumbnail.png differ
diff --git a/tools/fuse.js b/tools/fuse.js
index 719bf6ef..70aede3c 100644
--- a/tools/fuse.js
+++ b/tools/fuse.js
@@ -6,16 +6,15 @@
  * Client & Server compiler / bundler / watcher
  */
 
+const autoprefixer = require('autoprefixer')
 const colors = require('colors/safe')
 const fsbx = require('fuse-box')
 const nodemon = require('nodemon')
-const babel = require('babel-core')
-const uglify = require('uglify-es')
 const fs = require('fs-extra')
 
-// ======================================================
+// -------------------------------------------------------
 // Parse cmd arguments
-// ======================================================
+// -------------------------------------------------------
 
 const args = require('yargs')
   .option('d', {
@@ -23,30 +22,21 @@ const args = require('yargs')
     describe: 'Start in Developer mode',
     type: 'boolean'
   })
-  .option('c', {
-    alias: 'dev-configure',
-    describe: 'Start in Configure Developer mode',
-    type: 'boolean'
-  })
   .help('h')
   .alias('h', 'help')
   .argv
 
-let mode = 'build'
-const dev = args.d || args.c
-if (args.d) {
+const dev = args.dev
+
+if (dev) {
   console.info(colors.bgWhite.black(' Starting Fuse in DEVELOPER mode... '))
-  mode = 'dev'
-} else if (args.c) {
-  console.info(colors.bgWhite.black(' Starting Fuse in CONFIGURE DEVELOPER mode... '))
-  mode = 'dev-configure'
 } else {
   console.info(colors.bgWhite.black(' Starting Fuse in BUILD mode... '))
 }
 
-// ======================================================
+// -------------------------------------------------------
 // BUILD VARS
-// ======================================================
+// -------------------------------------------------------
 
 const ALIASES = {
   'brace-ext-modelist': 'brace/ext/modelist.js',
@@ -71,16 +61,31 @@ const SHIMS = {
   }
 }
 
-// ======================================================
+// -------------------------------------------------------
 // Global Tasks
-// ======================================================
+// -------------------------------------------------------
 
 console.info(colors.white('└── ') + colors.green('Running global tasks...'))
 let globalTasks = require('./fuse_tasks')
 
-// ======================================================
-// Fuse Tasks
-// ======================================================
+// -------------------------------------------------------
+// FUSEBOX PRODUCER
+// -------------------------------------------------------
+
+const babelrc = fs.readJsonSync('.babelrc')
+const scssChain = [
+  fsbx.SassPlugin({
+    includePaths: ['node_modules'],
+    outputStyle: dev ? 'nested' : 'compressed'
+  }),
+  fsbx.PostCSS([
+    autoprefixer({
+      remove: false,
+      browsers: babelrc.presets[0][1].targets.browsers
+    })
+  ]),
+  fsbx.CSSPlugin()
+]
 
 globalTasks.then(() => {
   let fuse = fsbx.FuseBox.init({
@@ -91,100 +96,60 @@ globalTasks.then(() => {
     tsConfig: './tsconfig.json',
     plugins: [
       fsbx.EnvPlugin({ NODE_ENV: (dev) ? 'development' : 'production' }),
-      fsbx.VuePlugin(),
-      ['.scss', fsbx.SassPlugin({ outputStyle: (dev) ? 'nested' : 'compressed' }), fsbx.CSSPlugin()],
-      fsbx.BabelPlugin({ comments: false, presets: ['es2015'] }),
+      fsbx.VueComponentPlugin({
+        script: fsbx.BabelPlugin(babelrc),
+        template: fsbx.ConsolidatePlugin({
+          engine: 'pug'
+        }),
+        style: scssChain
+      }),
+      scssChain,
+      fsbx.BabelPlugin(babelrc),
       fsbx.JSONPlugin()
-      /* !dev && fsbx.QuantumPlugin({
-        target: 'browser',
-        uglify: true,
-        api: (core) => {
-          core.solveComputed('default/js/components/editor-codeblock.vue', {
-            mapping: '/js/ace/ace.js',
-            fn: (statement, core) => {
-              statement.setExpression(`'/js/ace/ace.js'`)
-            }
-          })
-          core.solveComputed('default/js/components/editor.component.js', {
-            mapping: '/js/simplemde/simplemde.min.js',
-            fn: (statement, core) => {
-              statement.setExpression(`'/js/simplemde/simplemde.min.js'`)
-            }
-          })
-        }
-      }) */
-      // !dev && fsbx.UglifyESPlugin()
     ],
     debug: false,
     log: true
   })
 
-  const bundleVendor = fuse.bundle('vendor').shim(SHIMS).instructions('~ index.js') // eslint-disable-line no-unused-vars
-  const bundleApp = fuse.bundle('app').instructions('!> [index.js]')
-  // const bundleApp = fuse.bundle('app').shim(SHIMS).instructions('> index.js')
-  const bundleSetup = fuse.bundle('configure').instructions('> configure.js')
+  // -------------------------------------------------------
+  // FUSEBOX DEV
+  // -------------------------------------------------------
 
-  switch (mode) {
-    case 'dev':
-      bundleApp.watch()
-      break
-    case 'dev-configure':
-      bundleSetup.watch()
-      break
+  if (dev) {
+    fuse.dev({
+      port: 5555,
+      httpServer: false
+    })
   }
 
+  // -------------------------------------------------------
+  // FUSEBOX BUNDLES
+  // -------------------------------------------------------
+
+  if (dev) {
+    fuse.bundle('libs').shim(SHIMS).instructions('~ index.js')
+    fuse.bundle('app').instructions('!> [index.js]').hmr({ reload: true }).watch()
+  } else {
+    fuse.bundle('bundle.min.js').shim(SHIMS).instructions('> index.js')
+  }
+
+  // -------------------------------------------------------
+  // FUSEBOX RUN
+  // -------------------------------------------------------
+
   fuse.run().then(() => {
     console.info(colors.green.bold('\nAssets compilation + bundling completed.'))
 
     if (dev) {
       nodemon({
-        exec: (args.d) ? 'node server' : 'node wiki configure',
-        ignore: ['assets/', 'client/', 'data/', 'repo/', 'tests/'],
-        ext: 'js json',
-        watch: (args.d) ? ['server'] : ['server/configure.js'],
+        exec: 'node server',
+        ignore: ['assets/', 'client/', 'data/', 'repo/', 'tests/', 'tools/'],
+        ext: 'js json graphql',
+        watch: ['server'],
         env: { 'NODE_ENV': 'development' }
       })
-    } else {
-      console.info(colors.yellow.bold('\nTranspiling vendor bundle...'))
-      let appCode = babel.transform(fs.readFileSync('./assets/js/app.js', 'utf8'), {
-        babelrc: false,
-        compact: false,
-        filename: 'app.js',
-        plugins: ['transform-object-assign']
-      }).code
-      let vendorCode = babel.transform(fs.readFileSync('./assets/js/vendor.js', 'utf8'), {
-        babelrc: false,
-        comments: false,
-        compact: false,
-        filename: 'vendor.js',
-        plugins: [
-          'transform-es2015-arrow-functions',
-          'transform-es2015-block-scoped-functions',
-          'transform-es2015-block-scoping',
-          'transform-es2015-classes',
-          'transform-es2015-computed-properties',
-          'transform-es2015-destructuring',
-          'transform-es2015-duplicate-keys',
-          'transform-es2015-for-of',
-          'transform-es2015-function-name',
-          'transform-es2015-literals',
-          'transform-es2015-object-super',
-          'transform-es2015-parameters',
-          'transform-es2015-shorthand-properties',
-          'transform-es2015-spread',
-          'transform-es2015-sticky-regex',
-          'transform-es2015-template-literals',
-          'transform-es2015-typeof-symbol',
-          'transform-es2015-unicode-regex'
-        ]
-      }).code
-      console.info(colors.yellow.bold('Minifing bundles...'))
-      fs.writeFileSync('./assets/js/vendor.js', uglify.minify(vendorCode).code, 'utf8')
-      fs.writeFileSync('./assets/js/app.js', uglify.minify(appCode).code, 'utf8')
-      fs.writeFileSync('./assets/js/configure.js', uglify.minify(fs.readFileSync('./assets/js/configure.js', 'utf8')).code, 'utf8')
-      console.info(colors.green.bold('\nBUILD SUCCEEDED.'))
-      return true
     }
+    return true
   }).catch(err => {
     console.error(colors.red(' X Bundle compilation failed! ' + err.message))
     process.exit(1)
diff --git a/tools/fuse_tasks.js b/tools/fuse_tasks.js
index 90e7b61b..c9d0ee03 100644
--- a/tools/fuse_tasks.js
+++ b/tools/fuse_tasks.js
@@ -65,27 +65,6 @@ module.exports = Promise.mapSeries([
       }
     })
   },
-  /**
-   * i18n
-   */
-  () => {
-    console.info(colors.white('  └── ') + colors.green('Copying i18n client files...'))
-    return fs.ensureDirAsync('./assets/js/i18n').then(() => {
-      return fs.readJsonAsync('./server/locales/en/browser.json').then(enContent => {
-        return fs.readdirAsync('./server/locales').then(langs => {
-          return Promise.map(langs, lang => {
-            console.info(colors.white('      ' + lang + '.json'))
-            let outputPath = path.join('./assets/js/i18n', lang + '.json')
-            return fs.readJsonAsync(path.join('./server/locales', lang, 'browser.json'), 'utf8').then((content) => {
-              return fs.outputJsonAsync(outputPath, _.defaultsDeep(content, enContent))
-            }).catch(err => { // eslint-disable-line handle-callback-err
-              return fs.outputJsonAsync(outputPath, enContent)
-            })
-          })
-        })
-      })
-    })
-  },
   /**
    * Delete Fusebox cache
    */
diff --git a/wiki.js b/wiki.js
index fcfb1358..4f14f1bb 100644
--- a/wiki.js
+++ b/wiki.js
@@ -1,13 +1,72 @@
 #!/usr/bin/env node
-'use strict'
 
 // ===========================================
 // Wiki.js
-// 1.0.0
+// 2.0
 // Licensed under AGPLv3
 // ===========================================
 
-const init = require('./server/init')
+const Promise = require('bluebird')
+const fs = Promise.promisifyAll(require('fs-extra'))
+const pm2 = Promise.promisifyAll(require('pm2'))
+const ora = require('ora')
+const path = require('path')
+
+const ROOTPATH = process.cwd()
+
+const init = {
+  /**
+   * Start in background mode
+   */
+  start () {
+    let spinner = ora('Initializing...').start()
+    return fs.emptyDirAsync(path.join(ROOTPATH, './logs')).then(() => {
+      return pm2.connectAsync().then(() => {
+        return pm2.startAsync({
+          name: 'wiki',
+          script: 'server',
+          cwd: ROOTPATH,
+          output: path.join(ROOTPATH, './logs/wiki-output.log'),
+          error: path.join(ROOTPATH, './logs/wiki-error.log'),
+          minUptime: 5000,
+          maxRestarts: 5
+        }).then(() => {
+          spinner.succeed('Wiki.js has started successfully.')
+        }).finally(() => {
+          pm2.disconnect()
+        })
+      })
+    }).catch(err => {
+      spinner.fail(err)
+      process.exit(1)
+    })
+  },
+  /**
+   * Stop Wiki.js process(es)
+   */
+  stop () {
+    let spinner = ora('Shutting down Wiki.js...').start()
+    return pm2.connectAsync().then(() => {
+      return pm2.stopAsync('wiki').then(() => {
+        spinner.succeed('Wiki.js has stopped successfully.')
+      }).finally(() => {
+        pm2.disconnect()
+      })
+    }).catch(err => {
+      spinner.fail(err)
+      process.exit(1)
+    })
+  },
+  /**
+   * Restart Wiki.js process(es)
+   */
+  restart: function () {
+    let self = this
+    return self.stop().delay(1000).then(() => {
+      self.startDetect()
+    })
+  }
+}
 
 require('yargs') // eslint-disable-line no-unused-expressions
   .usage('Usage: node $0 <cmd> [args]')
@@ -16,7 +75,7 @@ require('yargs') // eslint-disable-line no-unused-expressions
     alias: ['boot', 'init'],
     desc: 'Start Wiki.js process',
     handler: argv => {
-      init.startDetect()
+      init.start()
     }
   })
   .command({
@@ -35,18 +94,9 @@ require('yargs') // eslint-disable-line no-unused-expressions
       init.restart()
     }
   })
-  .command({
-    command: 'configure [port]',
-    alias: ['config', 'conf', 'cfg', 'setup'],
-    desc: 'Configure Wiki.js using the web-based setup wizard',
-    builder: (yargs) => yargs.default('port', 3000),
-    handler: argv => {
-      init.configure(argv.port)
-    }
-  })
   .recommendCommands()
   .demandCommand(1, 'You must provide one of the accepted commands above.')
   .help()
   .version()
-  .epilogue('Read the docs at https://wiki.requarks.io')
+  .epilogue('Read the docs at https://docs.requarks.io/wiki')
   .argv
diff --git a/yarn.lock b/yarn.lock
index e1e9f9f2..343424e2 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -48,7 +48,7 @@
     lru-cache "^4.0.0"
     moment "^2.16.1"
 
-"@glimpse/glimpse@~0.22.15":
+"@glimpse/glimpse@0.22.15":
   version "0.22.15"
   resolved "https://registry.yarnpkg.com/@glimpse/glimpse/-/glimpse-0.22.15.tgz#593adafc9173bafa6aa6dab301575b9ce88e6ece"
   dependencies:
@@ -58,9 +58,9 @@
     command-line-usage "^4.0.0"
     lodash "^4.15.0"
 
-"@panter/vue-i18next@~0.5.0":
-  version "0.5.1"
-  resolved "https://registry.yarnpkg.com/@panter/vue-i18next/-/vue-i18next-0.5.1.tgz#714bbeb62c25850231f2681ad11142d3c6e3c645"
+"@panter/vue-i18next@0.6.1":
+  version "0.6.1"
+  resolved "https://registry.yarnpkg.com/@panter/vue-i18next/-/vue-i18next-0.6.1.tgz#11228dd34e28db741c9c71ba90854afeb761b563"
 
 "@types/express-serve-static-core@*":
   version "4.0.49"
@@ -75,6 +75,22 @@
     "@types/express-serve-static-core" "*"
     "@types/serve-static" "*"
 
+"@types/geojson@^1.0.0":
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-1.0.2.tgz#b02d10ab028e2928ac592a051aaa4981a1941d03"
+
+"@types/graphql@0.10.2":
+  version "0.10.2"
+  resolved "https://registry.yarnpkg.com/@types/graphql/-/graphql-0.10.2.tgz#d7c79acbaa17453b6681c80c34b38fcb10c4c08c"
+
+"@types/graphql@^0.11.4":
+  version "0.11.5"
+  resolved "https://registry.yarnpkg.com/@types/graphql/-/graphql-0.11.5.tgz#e70f051e80b299be5b12f7e60d962f30c9596072"
+
+"@types/graphql@^0.9.0":
+  version "0.9.4"
+  resolved "https://registry.yarnpkg.com/@types/graphql/-/graphql-0.9.4.tgz#cdeb6bcbef9b6c584374b81aa7f48ecf3da404fa"
+
 "@types/ldapjs@^1.0.0":
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/@types/ldapjs/-/ldapjs-1.0.0.tgz#d940cb412140caec14edaa9c76d5b92799dab495"
@@ -89,7 +105,7 @@
   version "8.0.14"
   resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.14.tgz#4a19dc6bb61d16c01cbadc7b30ac23518fff176b"
 
-"@types/node@^6.0.46":
+"@types/node@^6.0.46", "@types/node@^6.0.48":
   version "6.0.84"
   resolved "https://registry.yarnpkg.com/@types/node/-/node-6.0.84.tgz#193ffe5a9f42864d425ffd9739d95b753c6a1eab"
 
@@ -110,13 +126,6 @@
     "@types/express-serve-static-core" "*"
     "@types/mime" "*"
 
-JSONStream@^1.2.1:
-  version "1.3.1"
-  resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.1.tgz#707f761e01dae9e16f1bcf93703b78c70966579a"
-  dependencies:
-    jsonparse "^1.2.0"
-    through ">=2.2.7 <3"
-
 abab@^1.0.3:
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/abab/-/abab-1.0.3.tgz#b81de5f7274ec4e756d797cd834f303642724e5d"
@@ -125,25 +134,6 @@ abbrev@1:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.0.tgz#d0554c2256636e2f56e7c2e5ad183f859428d81f"
 
-abstract-leveldown@2.4.1, abstract-leveldown@~2.4.0:
-  version "2.4.1"
-  resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.4.1.tgz#b3bfedb884eb693a12775f0c55e9f0a420ccee64"
-  dependencies:
-    xtend "~4.0.0"
-
-abstract-leveldown@~2.6.1:
-  version "2.6.1"
-  resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.6.1.tgz#f9014a5669b746418e145168dea49a044ae15900"
-  dependencies:
-    xtend "~4.0.0"
-
-accepts@1.3.3, accepts@~1.3.3:
-  version "1.3.3"
-  resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.3.tgz#c3ca7434938648c3e0d9c1e328dd68b622c284ca"
-  dependencies:
-    mime-types "~2.1.11"
-    negotiator "0.6.1"
-
 accepts@~1.2.12:
   version "1.2.13"
   resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.2.13.tgz#e5f1f3928c6d95fd96558c36ec3d9d0de4a6ecea"
@@ -151,6 +141,20 @@ accepts@~1.2.12:
     mime-types "~2.1.6"
     negotiator "0.5.3"
 
+accepts@~1.3.3:
+  version "1.3.3"
+  resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.3.tgz#c3ca7434938648c3e0d9c1e328dd68b622c284ca"
+  dependencies:
+    mime-types "~2.1.11"
+    negotiator "0.6.1"
+
+accepts@~1.3.4:
+  version "1.3.4"
+  resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.4.tgz#86246758c7dd6d21a6474ff084a4740ec05eb21f"
+  dependencies:
+    mime-types "~2.1.16"
+    negotiator "0.6.1"
+
 acorn-es7-plugin@^1.1.7:
   version "1.1.7"
   resolved "https://registry.yarnpkg.com/acorn-es7-plugin/-/acorn-es7-plugin-1.1.7.tgz#f2ee1f3228a90eead1245f9ab1922eb2e71d336b"
@@ -179,6 +183,12 @@ acorn-jsx@^4.0.1:
   dependencies:
     acorn "^5.0.3"
 
+acorn-object-rest-spread@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/acorn-object-rest-spread/-/acorn-object-rest-spread-1.1.0.tgz#78699aefdd18ec3182caadadf52e2697c048f476"
+  dependencies:
+    acorn "^5.0.3"
+
 acorn@^2.6.4:
   version "2.7.0"
   resolved "https://registry.yarnpkg.com/acorn/-/acorn-2.7.0.tgz#ab6e7d9d886aaca8b085bc3312b79a198433f0e7"
@@ -195,10 +205,6 @@ acorn@^5.0.3, acorn@^5.1.1:
   version "5.1.1"
   resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.1.1.tgz#53fe161111f912ab999ee887a90a0bc52822fd75"
 
-after@0.8.2:
-  version "0.8.2"
-  resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f"
-
 ajax-request@^1.2.0:
   version "1.2.3"
   resolved "https://registry.yarnpkg.com/ajax-request/-/ajax-request-1.2.3.tgz#99fcbec1d6d2792f85fa949535332bd14f5f3790"
@@ -217,6 +223,15 @@ ajv@^4.7.0, ajv@^4.9.1:
     co "^4.6.0"
     json-stable-stringify "^1.0.1"
 
+ajv@^5.1.0:
+  version "5.2.3"
+  resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.2.3.tgz#c06f598778c44c6b161abafe3466b81ad1814ed2"
+  dependencies:
+    co "^4.6.0"
+    fast-deep-equal "^1.0.0"
+    json-schema-traverse "^0.3.0"
+    json-stable-stringify "^1.0.1"
+
 ajv@^5.2.0:
   version "5.2.2"
   resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.2.2.tgz#47c68d69e86f5d953103b0074a9430dc63da5e39"
@@ -248,13 +263,19 @@ amp@0.3.1, amp@~0.3.1:
   version "0.3.1"
   resolved "https://registry.yarnpkg.com/amp/-/amp-0.3.1.tgz#6adf8d58a74f361e82c1fa8d389c079e139fc47d"
 
-ansi-escape-sequences@^4.0.0:
-  version "4.0.0"
-  resolved "https://registry.yarnpkg.com/ansi-escape-sequences/-/ansi-escape-sequences-4.0.0.tgz#e0ecb042958b71e42942d35c1fcf1d9b00a0f67e"
+ansi-align@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-2.0.0.tgz#c36aeccba563b89ceb556f3690f0b1d9e3547f7f"
   dependencies:
-    array-back "^2.0.0"
+    string-width "^2.0.0"
 
-ansi-escapes@^1.1.0, ansi-escapes@^1.4.0:
+ansi-escape-sequences@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/ansi-escape-sequences/-/ansi-escape-sequences-3.0.0.tgz#1c18394b6af9b76ff9a63509fa497669fd2ce53e"
+  dependencies:
+    array-back "^1.0.3"
+
+ansi-escapes@^1.1.0:
   version "1.4.0"
   resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e"
 
@@ -262,7 +283,11 @@ ansi-escapes@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-2.0.0.tgz#5bae52be424878dd9783e8910e3fc2922e83c81b"
 
-ansi-regex@^2.0.0, ansi-regex@^2.1.1:
+ansi-escapes@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.0.0.tgz#ec3e8b4e9f8064fc02c3ac9b65f1c275bda8ef92"
+
+ansi-regex@^2.0.0:
   version "2.1.1"
   resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
 
@@ -274,12 +299,18 @@ ansi-styles@^2.2.1:
   version "2.2.1"
   resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
 
-ansi-styles@^3.0.0, ansi-styles@^3.1.0:
+ansi-styles@^3.1.0:
   version "3.1.0"
   resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.1.0.tgz#09c202d5c917ec23188caa5c9cb9179cd9547750"
   dependencies:
     color-convert "^1.0.0"
 
+ansi-styles@^3.2.0:
+  version "3.2.0"
+  resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.0.tgz#c159b8d5be0f9e5a6f346dab94f16ce022161b88"
+  dependencies:
+    color-convert "^1.9.0"
+
 ansi@^0.3.1:
   version "0.3.1"
   resolved "https://registry.yarnpkg.com/ansi/-/ansi-0.3.1.tgz#0c42d4fb17160d5a9af1e484bace1c66922c1b21"
@@ -295,6 +326,63 @@ anymatch@^1.3.0:
     arrify "^1.0.0"
     micromatch "^2.1.5"
 
+apollo-client@^1.9.3:
+  version "1.9.3"
+  resolved "https://registry.yarnpkg.com/apollo-client/-/apollo-client-1.9.3.tgz#37000b3c801f4571b7b089739e696a158896aeab"
+  dependencies:
+    apollo-link-core "^0.5.0"
+    graphql "^0.10.0"
+    graphql-anywhere "^3.0.1"
+    graphql-tag "^2.0.0"
+    redux "^3.4.0"
+    symbol-observable "^1.0.2"
+    whatwg-fetch "^2.0.0"
+  optionalDependencies:
+    "@types/graphql" "0.10.2"
+
+apollo-link-core@^0.5.0:
+  version "0.5.4"
+  resolved "https://registry.yarnpkg.com/apollo-link-core/-/apollo-link-core-0.5.4.tgz#8efd4cd747959872a32f313f0ccfc2a76b396668"
+  dependencies:
+    graphql "^0.10.3"
+    graphql-tag "^2.4.2"
+    zen-observable-ts "^0.4.4"
+
+apollo-link@^0.7.0:
+  version "0.7.0"
+  resolved "https://registry.yarnpkg.com/apollo-link/-/apollo-link-0.7.0.tgz#a8f09069b31821c27285584264356b1b6e6be6f2"
+  dependencies:
+    apollo-utilities "^0.2.0-beta.0"
+    graphql "^0.11.3"
+    zen-observable-ts "^0.5.0"
+
+apollo-server-core@^1.1.3:
+  version "1.1.3"
+  resolved "https://registry.yarnpkg.com/apollo-server-core/-/apollo-server-core-1.1.3.tgz#1c1f223ab96097e095969a3494e6408cefdc9689"
+  dependencies:
+    apollo-tracing "^0.0.7"
+
+apollo-server-express@1.1.3:
+  version "1.1.3"
+  resolved "https://registry.yarnpkg.com/apollo-server-express/-/apollo-server-express-1.1.3.tgz#ccca554327458a91c9ff3216bb6998fccb6ad9e4"
+  dependencies:
+    apollo-server-core "^1.1.3"
+    apollo-server-module-graphiql "^1.1.3"
+
+apollo-server-module-graphiql@^1.1.3:
+  version "1.1.3"
+  resolved "https://registry.yarnpkg.com/apollo-server-module-graphiql/-/apollo-server-module-graphiql-1.1.3.tgz#cf59be3320fda301ef369660697486f172457abb"
+
+apollo-tracing@^0.0.7:
+  version "0.0.7"
+  resolved "https://registry.yarnpkg.com/apollo-tracing/-/apollo-tracing-0.0.7.tgz#78466cfefdb52a0802a57b488d26a1a67a25909f"
+  dependencies:
+    graphql-tools "^1.1.0"
+
+apollo-utilities@^0.2.0-beta.0:
+  version "0.2.0-beta.2"
+  resolved "https://registry.yarnpkg.com/apollo-utilities/-/apollo-utilities-0.2.0-beta.2.tgz#95b61e00fa0cb67f6af65921484bca33114d55e1"
+
 app-root-path@^1.3.0:
   version "1.4.0"
   resolved "https://registry.yarnpkg.com/app-root-path/-/app-root-path-1.4.0.tgz#6335d865c9640d0fad99004e5a79232238e92dfa"
@@ -352,12 +440,6 @@ array-back@^1.0.3, array-back@^1.0.4:
   dependencies:
     typical "^2.6.0"
 
-array-back@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/array-back/-/array-back-2.0.0.tgz#6877471d51ecc9c9bfa6136fb6c7d5fe69748022"
-  dependencies:
-    typical "^2.6.1"
-
 array-equal@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93"
@@ -384,10 +466,6 @@ array-unique@^0.2.1:
   version "0.2.1"
   resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53"
 
-arraybuffer.slice@0.0.6:
-  version "0.0.6"
-  resolved "https://registry.yarnpkg.com/arraybuffer.slice/-/arraybuffer.slice-0.0.6.tgz#f33b2159f0532a3f3107a272c0ccfbd1ad2979ca"
-
 arrify@^1.0.0, arrify@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
@@ -412,6 +490,10 @@ assert-plus@^0.2.0:
   version "0.2.0"
   resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234"
 
+astral-regex@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9"
+
 async-each@^1.0.0:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d"
@@ -431,22 +513,12 @@ async@1.5, async@^1.4.0, async@^1.5:
   version "1.5.2"
   resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a"
 
-async@2.1.4:
-  version "2.1.4"
-  resolved "https://registry.yarnpkg.com/async/-/async-2.1.4.tgz#2d2160c7788032e4dd6cbe2502f1f9a2c8f6cde4"
-  dependencies:
-    lodash "^4.14.0"
-
-async@^2.1.4, async@^2.3.0, async@^2.5:
+async@^2.1.4, async@^2.5:
   version "2.5.0"
   resolved "https://registry.yarnpkg.com/async/-/async-2.5.0.tgz#843190fd6b7357a0b9e1c956edddd5ec8462b54d"
   dependencies:
     lodash "^4.14.0"
 
-async@~0.2.6:
-  version "0.2.10"
-  resolved "https://registry.yarnpkg.com/async/-/async-0.2.10.tgz#b6bbe0b0674b9d719708ca38de8c237cb526c3d1"
-
 async@~1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/async/-/async-1.0.0.tgz#f8fc04ca3a13784ade9e1641af98578cfbd647a9"
@@ -455,26 +527,41 @@ asynckit@^0.4.0:
   version "0.4.0"
   resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
 
-auto-load@~3.0.0:
+auto-load@3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/auto-load/-/auto-load-3.0.0.tgz#f3c91d15120a32c89524b420d7283584c72088aa"
 
+autoprefixer@7.1.5:
+  version "7.1.5"
+  resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-7.1.5.tgz#d65d14b83c7cd1dd7bc801daa00557addf5a06b2"
+  dependencies:
+    browserslist "^2.5.0"
+    caniuse-lite "^1.0.30000744"
+    normalize-range "^0.1.2"
+    num2fraction "^1.2.2"
+    postcss "^6.0.13"
+    postcss-value-parser "^3.2.3"
+
 aws-sign2@~0.6.0:
   version "0.6.0"
   resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f"
 
-aws4@^1.2.1:
+aws-sign2@~0.7.0:
+  version "0.7.0"
+  resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8"
+
+aws4@^1.2.1, aws4@^1.6.0:
   version "1.6.0"
   resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e"
 
-axios@~0.16.2:
+axios@0.16.2:
   version "0.16.2"
   resolved "https://registry.yarnpkg.com/axios/-/axios-0.16.2.tgz#ba4f92f17167dfbab40983785454b9ac149c3c6d"
   dependencies:
     follow-redirects "^1.2.3"
     is-buffer "^1.1.5"
 
-babel-cli@~6.26.0:
+babel-cli@6.26.0:
   version "6.26.0"
   resolved "https://registry.yarnpkg.com/babel-cli/-/babel-cli-6.26.0.tgz#502ab54874d7db88ad00b887a06383ce03d002f1"
   dependencies:
@@ -511,6 +598,30 @@ babel-code-frame@^6.26.0:
     esutils "^2.0.2"
     js-tokens "^3.0.2"
 
+babel-core@6.26.0, babel-core@^6.26.0:
+  version "6.26.0"
+  resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.0.tgz#af32f78b31a6fcef119c87b0fd8d9753f03a0bb8"
+  dependencies:
+    babel-code-frame "^6.26.0"
+    babel-generator "^6.26.0"
+    babel-helpers "^6.24.1"
+    babel-messages "^6.23.0"
+    babel-register "^6.26.0"
+    babel-runtime "^6.26.0"
+    babel-template "^6.26.0"
+    babel-traverse "^6.26.0"
+    babel-types "^6.26.0"
+    babylon "^6.18.0"
+    convert-source-map "^1.5.0"
+    debug "^2.6.8"
+    json5 "^0.5.1"
+    lodash "^4.17.4"
+    minimatch "^3.0.4"
+    path-is-absolute "^1.0.1"
+    private "^0.1.7"
+    slash "^1.0.0"
+    source-map "^0.5.6"
+
 babel-core@^6.0.0, babel-core@^6.24.1:
   version "6.25.0"
   resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.25.0.tgz#7dd42b0463c742e9d5296deb3ec67a9322dad729"
@@ -535,30 +646,6 @@ babel-core@^6.0.0, babel-core@^6.24.1:
     slash "^1.0.0"
     source-map "^0.5.0"
 
-babel-core@^6.26.0:
-  version "6.26.0"
-  resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.0.tgz#af32f78b31a6fcef119c87b0fd8d9753f03a0bb8"
-  dependencies:
-    babel-code-frame "^6.26.0"
-    babel-generator "^6.26.0"
-    babel-helpers "^6.24.1"
-    babel-messages "^6.23.0"
-    babel-register "^6.26.0"
-    babel-runtime "^6.26.0"
-    babel-template "^6.26.0"
-    babel-traverse "^6.26.0"
-    babel-types "^6.26.0"
-    babylon "^6.18.0"
-    convert-source-map "^1.5.0"
-    debug "^2.6.8"
-    json5 "^0.5.1"
-    lodash "^4.17.4"
-    minimatch "^3.0.4"
-    path-is-absolute "^1.0.1"
-    private "^0.1.7"
-    slash "^1.0.0"
-    source-map "^0.5.6"
-
 babel-generator@^6.18.0, babel-generator@^6.25.0:
   version "6.25.0"
   resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.25.0.tgz#33a1af70d5f2890aeb465a4a7793c1df6a9ea9fc"
@@ -585,6 +672,22 @@ babel-generator@^6.26.0:
     source-map "^0.5.6"
     trim-right "^1.0.1"
 
+babel-helper-bindify-decorators@^6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz#14c19e5f142d7b47f19a52431e52b1ccbc40a330"
+  dependencies:
+    babel-runtime "^6.22.0"
+    babel-traverse "^6.24.1"
+    babel-types "^6.24.1"
+
+babel-helper-builder-binary-assignment-operator-visitor@^6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz#cce4517ada356f4220bcae8a02c2b346f9a56664"
+  dependencies:
+    babel-helper-explode-assignable-expression "^6.24.1"
+    babel-runtime "^6.22.0"
+    babel-types "^6.24.1"
+
 babel-helper-call-delegate@^6.24.1:
   version "6.24.1"
   resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz#ece6aacddc76e41c3461f88bfc575bd0daa2df8d"
@@ -603,6 +706,23 @@ babel-helper-define-map@^6.24.1:
     babel-types "^6.24.1"
     lodash "^4.2.0"
 
+babel-helper-explode-assignable-expression@^6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz#f25b82cf7dc10433c55f70592d5746400ac22caa"
+  dependencies:
+    babel-runtime "^6.22.0"
+    babel-traverse "^6.24.1"
+    babel-types "^6.24.1"
+
+babel-helper-explode-class@^6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz#7dc2a3910dee007056e1e31d640ced3d54eaa9eb"
+  dependencies:
+    babel-helper-bindify-decorators "^6.24.1"
+    babel-runtime "^6.22.0"
+    babel-traverse "^6.24.1"
+    babel-types "^6.24.1"
+
 babel-helper-function-name@^6.24.1:
   version "6.24.1"
   resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9"
@@ -642,6 +762,16 @@ babel-helper-regex@^6.24.1:
     babel-types "^6.24.1"
     lodash "^4.2.0"
 
+babel-helper-remap-async-to-generator@^6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz#5ec581827ad723fecdd381f1c928390676e4551b"
+  dependencies:
+    babel-helper-function-name "^6.24.1"
+    babel-runtime "^6.22.0"
+    babel-template "^6.24.1"
+    babel-traverse "^6.24.1"
+    babel-types "^6.24.1"
+
 babel-helper-replace-supers@^6.24.1:
   version "6.24.1"
   resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz#bf6dbfe43938d17369a213ca8a8bf74b6a90ab1a"
@@ -660,13 +790,12 @@ babel-helpers@^6.24.1:
     babel-runtime "^6.22.0"
     babel-template "^6.24.1"
 
-babel-jest@^20.0.3, babel-jest@~20.0.3:
-  version "20.0.3"
-  resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-20.0.3.tgz#e4a03b13dc10389e140fc645d09ffc4ced301671"
+babel-jest@21.2.0, babel-jest@^21.2.0:
+  version "21.2.0"
+  resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-21.2.0.tgz#2ce059519a9374a2c46f2455b6fbef5ad75d863e"
   dependencies:
-    babel-core "^6.0.0"
     babel-plugin-istanbul "^4.0.0"
-    babel-preset-jest "^20.0.3"
+    babel-preset-jest "^21.2.0"
 
 babel-messages@^6.23.0:
   version "6.23.0"
@@ -688,9 +817,76 @@ babel-plugin-istanbul@^4.0.0:
     istanbul-lib-instrument "^1.7.2"
     test-exclude "^4.1.1"
 
-babel-plugin-jest-hoist@^20.0.3:
-  version "20.0.3"
-  resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-20.0.3.tgz#afedc853bd3f8dc3548ea671fbe69d03cc2c1767"
+babel-plugin-jest-hoist@^21.2.0:
+  version "21.2.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-21.2.0.tgz#2cef637259bd4b628a6cace039de5fcd14dbb006"
+
+babel-plugin-syntax-async-functions@^6.8.0:
+  version "6.13.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95"
+
+babel-plugin-syntax-async-generators@^6.5.0:
+  version "6.13.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz#6bc963ebb16eccbae6b92b596eb7f35c342a8b9a"
+
+babel-plugin-syntax-class-properties@^6.8.0:
+  version "6.13.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz#d7eb23b79a317f8543962c505b827c7d6cac27de"
+
+babel-plugin-syntax-decorators@^6.13.0:
+  version "6.13.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz#312563b4dbde3cc806cee3e416cceeaddd11ac0b"
+
+babel-plugin-syntax-dynamic-import@^6.18.0:
+  version "6.18.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz#8d6a26229c83745a9982a441051572caa179b1da"
+
+babel-plugin-syntax-exponentiation-operator@^6.8.0:
+  version "6.13.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de"
+
+babel-plugin-syntax-object-rest-spread@^6.13.0, babel-plugin-syntax-object-rest-spread@^6.8.0:
+  version "6.13.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5"
+
+babel-plugin-syntax-trailing-function-commas@^6.22.0:
+  version "6.22.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3"
+
+babel-plugin-transform-async-generator-functions@^6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz#f058900145fd3e9907a6ddf28da59f215258a5db"
+  dependencies:
+    babel-helper-remap-async-to-generator "^6.24.1"
+    babel-plugin-syntax-async-generators "^6.5.0"
+    babel-runtime "^6.22.0"
+
+babel-plugin-transform-async-to-generator@^6.22.0, babel-plugin-transform-async-to-generator@^6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz#6536e378aff6cb1d5517ac0e40eb3e9fc8d08761"
+  dependencies:
+    babel-helper-remap-async-to-generator "^6.24.1"
+    babel-plugin-syntax-async-functions "^6.8.0"
+    babel-runtime "^6.22.0"
+
+babel-plugin-transform-class-properties@^6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz#6a79763ea61d33d36f37b611aa9def81a81b46ac"
+  dependencies:
+    babel-helper-function-name "^6.24.1"
+    babel-plugin-syntax-class-properties "^6.8.0"
+    babel-runtime "^6.22.0"
+    babel-template "^6.24.1"
+
+babel-plugin-transform-decorators@^6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz#788013d8f8c6b5222bdf7b344390dfd77569e24d"
+  dependencies:
+    babel-helper-explode-class "^6.24.1"
+    babel-plugin-syntax-decorators "^6.13.0"
+    babel-runtime "^6.22.0"
+    babel-template "^6.24.1"
+    babel-types "^6.24.1"
 
 babel-plugin-transform-es2015-arrow-functions@^6.22.0:
   version "6.22.0"
@@ -704,6 +900,16 @@ babel-plugin-transform-es2015-block-scoped-functions@^6.22.0:
   dependencies:
     babel-runtime "^6.22.0"
 
+babel-plugin-transform-es2015-block-scoping@^6.23.0:
+  version "6.26.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz#d70f5299c1308d05c12f463813b0a09e73b1895f"
+  dependencies:
+    babel-runtime "^6.26.0"
+    babel-template "^6.26.0"
+    babel-traverse "^6.26.0"
+    babel-types "^6.26.0"
+    lodash "^4.17.4"
+
 babel-plugin-transform-es2015-block-scoping@^6.24.1:
   version "6.24.1"
   resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.24.1.tgz#76c295dc3a4741b1665adfd3167215dcff32a576"
@@ -714,7 +920,7 @@ babel-plugin-transform-es2015-block-scoping@^6.24.1:
     babel-types "^6.24.1"
     lodash "^4.2.0"
 
-babel-plugin-transform-es2015-classes@^6.24.1:
+babel-plugin-transform-es2015-classes@^6.23.0, babel-plugin-transform-es2015-classes@^6.24.1:
   version "6.24.1"
   resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db"
   dependencies:
@@ -728,33 +934,33 @@ babel-plugin-transform-es2015-classes@^6.24.1:
     babel-traverse "^6.24.1"
     babel-types "^6.24.1"
 
-babel-plugin-transform-es2015-computed-properties@^6.24.1:
+babel-plugin-transform-es2015-computed-properties@^6.22.0, babel-plugin-transform-es2015-computed-properties@^6.24.1:
   version "6.24.1"
   resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz#6fe2a8d16895d5634f4cd999b6d3480a308159b3"
   dependencies:
     babel-runtime "^6.22.0"
     babel-template "^6.24.1"
 
-babel-plugin-transform-es2015-destructuring@^6.22.0:
+babel-plugin-transform-es2015-destructuring@^6.22.0, babel-plugin-transform-es2015-destructuring@^6.23.0:
   version "6.23.0"
   resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d"
   dependencies:
     babel-runtime "^6.22.0"
 
-babel-plugin-transform-es2015-duplicate-keys@^6.24.1:
+babel-plugin-transform-es2015-duplicate-keys@^6.22.0, babel-plugin-transform-es2015-duplicate-keys@^6.24.1:
   version "6.24.1"
   resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz#73eb3d310ca969e3ef9ec91c53741a6f1576423e"
   dependencies:
     babel-runtime "^6.22.0"
     babel-types "^6.24.1"
 
-babel-plugin-transform-es2015-for-of@^6.22.0:
+babel-plugin-transform-es2015-for-of@^6.22.0, babel-plugin-transform-es2015-for-of@^6.23.0:
   version "6.23.0"
   resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691"
   dependencies:
     babel-runtime "^6.22.0"
 
-babel-plugin-transform-es2015-function-name@^6.24.1:
+babel-plugin-transform-es2015-function-name@^6.22.0, babel-plugin-transform-es2015-function-name@^6.24.1:
   version "6.24.1"
   resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz#834c89853bc36b1af0f3a4c5dbaa94fd8eacaa8b"
   dependencies:
@@ -768,7 +974,7 @@ babel-plugin-transform-es2015-literals@^6.22.0:
   dependencies:
     babel-runtime "^6.22.0"
 
-babel-plugin-transform-es2015-modules-amd@^6.24.1:
+babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015-modules-amd@^6.24.1:
   version "6.24.1"
   resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz#3b3e54017239842d6d19c3011c4bd2f00a00d154"
   dependencies:
@@ -776,6 +982,15 @@ babel-plugin-transform-es2015-modules-amd@^6.24.1:
     babel-runtime "^6.22.0"
     babel-template "^6.24.1"
 
+babel-plugin-transform-es2015-modules-commonjs@^6.23.0:
+  version "6.26.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz#0d8394029b7dc6abe1a97ef181e00758dd2e5d8a"
+  dependencies:
+    babel-plugin-transform-strict-mode "^6.24.1"
+    babel-runtime "^6.26.0"
+    babel-template "^6.26.0"
+    babel-types "^6.26.0"
+
 babel-plugin-transform-es2015-modules-commonjs@^6.24.1:
   version "6.24.1"
   resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.24.1.tgz#d3e310b40ef664a36622200097c6d440298f2bfe"
@@ -785,7 +1000,7 @@ babel-plugin-transform-es2015-modules-commonjs@^6.24.1:
     babel-template "^6.24.1"
     babel-types "^6.24.1"
 
-babel-plugin-transform-es2015-modules-systemjs@^6.24.1:
+babel-plugin-transform-es2015-modules-systemjs@^6.23.0, babel-plugin-transform-es2015-modules-systemjs@^6.24.1:
   version "6.24.1"
   resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz#ff89a142b9119a906195f5f106ecf305d9407d23"
   dependencies:
@@ -793,7 +1008,7 @@ babel-plugin-transform-es2015-modules-systemjs@^6.24.1:
     babel-runtime "^6.22.0"
     babel-template "^6.24.1"
 
-babel-plugin-transform-es2015-modules-umd@^6.24.1:
+babel-plugin-transform-es2015-modules-umd@^6.23.0, babel-plugin-transform-es2015-modules-umd@^6.24.1:
   version "6.24.1"
   resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz#ac997e6285cd18ed6176adb607d602344ad38468"
   dependencies:
@@ -801,14 +1016,14 @@ babel-plugin-transform-es2015-modules-umd@^6.24.1:
     babel-runtime "^6.22.0"
     babel-template "^6.24.1"
 
-babel-plugin-transform-es2015-object-super@^6.24.1:
+babel-plugin-transform-es2015-object-super@^6.22.0, babel-plugin-transform-es2015-object-super@^6.24.1:
   version "6.24.1"
   resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz#24cef69ae21cb83a7f8603dad021f572eb278f8d"
   dependencies:
     babel-helper-replace-supers "^6.24.1"
     babel-runtime "^6.22.0"
 
-babel-plugin-transform-es2015-parameters@^6.24.1:
+babel-plugin-transform-es2015-parameters@^6.23.0, babel-plugin-transform-es2015-parameters@^6.24.1:
   version "6.24.1"
   resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz#57ac351ab49caf14a97cd13b09f66fdf0a625f2b"
   dependencies:
@@ -819,7 +1034,7 @@ babel-plugin-transform-es2015-parameters@^6.24.1:
     babel-traverse "^6.24.1"
     babel-types "^6.24.1"
 
-babel-plugin-transform-es2015-shorthand-properties@^6.24.1:
+babel-plugin-transform-es2015-shorthand-properties@^6.22.0, babel-plugin-transform-es2015-shorthand-properties@^6.24.1:
   version "6.24.1"
   resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz#24f875d6721c87661bbd99a4622e51f14de38aa0"
   dependencies:
@@ -832,7 +1047,7 @@ babel-plugin-transform-es2015-spread@^6.22.0:
   dependencies:
     babel-runtime "^6.22.0"
 
-babel-plugin-transform-es2015-sticky-regex@^6.24.1:
+babel-plugin-transform-es2015-sticky-regex@^6.22.0, babel-plugin-transform-es2015-sticky-regex@^6.24.1:
   version "6.24.1"
   resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz#00c1cdb1aca71112cdf0cf6126c2ed6b457ccdbc"
   dependencies:
@@ -846,13 +1061,13 @@ babel-plugin-transform-es2015-template-literals@^6.22.0:
   dependencies:
     babel-runtime "^6.22.0"
 
-babel-plugin-transform-es2015-typeof-symbol@^6.22.0:
+babel-plugin-transform-es2015-typeof-symbol@^6.22.0, babel-plugin-transform-es2015-typeof-symbol@^6.23.0:
   version "6.23.0"
   resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372"
   dependencies:
     babel-runtime "^6.22.0"
 
-babel-plugin-transform-es2015-unicode-regex@^6.24.1:
+babel-plugin-transform-es2015-unicode-regex@^6.22.0, babel-plugin-transform-es2015-unicode-regex@^6.24.1:
   version "6.24.1"
   resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz#d38b12f42ea7323f729387f18a7c5ae1faeb35e9"
   dependencies:
@@ -860,12 +1075,27 @@ babel-plugin-transform-es2015-unicode-regex@^6.24.1:
     babel-runtime "^6.22.0"
     regexpu-core "^2.0.0"
 
-babel-plugin-transform-object-assign@~6.22.0:
-  version "6.22.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-assign/-/babel-plugin-transform-object-assign-6.22.0.tgz#f99d2f66f1a0b0d498e346c5359684740caa20ba"
+babel-plugin-transform-exponentiation-operator@^6.22.0, babel-plugin-transform-exponentiation-operator@^6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz#2ab0c9c7f3098fa48907772bb813fe41e8de3a0e"
   dependencies:
+    babel-helper-builder-binary-assignment-operator-visitor "^6.24.1"
+    babel-plugin-syntax-exponentiation-operator "^6.8.0"
     babel-runtime "^6.22.0"
 
+babel-plugin-transform-object-rest-spread@^6.22.0:
+  version "6.26.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz#0f36692d50fef6b7e2d4b3ac1478137a963b7b06"
+  dependencies:
+    babel-plugin-syntax-object-rest-spread "^6.8.0"
+    babel-runtime "^6.26.0"
+
+babel-plugin-transform-regenerator@^6.22.0:
+  version "6.26.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz#e0703696fbde27f0a3efcacf8b4dca2f7b3a8f2f"
+  dependencies:
+    regenerator-transform "^0.10.0"
+
 babel-plugin-transform-regenerator@^6.24.1:
   version "6.24.1"
   resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.24.1.tgz#b8da305ad43c3c99b4848e4fe4037b770d23c418"
@@ -895,7 +1125,42 @@ babel-polyfill@^6.26.0:
     core-js "^2.5.0"
     regenerator-runtime "^0.10.5"
 
-babel-preset-es2015@~6.24.1:
+babel-preset-env@1.6.0:
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.6.0.tgz#2de1c782a780a0a5d605d199c957596da43c44e4"
+  dependencies:
+    babel-plugin-check-es2015-constants "^6.22.0"
+    babel-plugin-syntax-trailing-function-commas "^6.22.0"
+    babel-plugin-transform-async-to-generator "^6.22.0"
+    babel-plugin-transform-es2015-arrow-functions "^6.22.0"
+    babel-plugin-transform-es2015-block-scoped-functions "^6.22.0"
+    babel-plugin-transform-es2015-block-scoping "^6.23.0"
+    babel-plugin-transform-es2015-classes "^6.23.0"
+    babel-plugin-transform-es2015-computed-properties "^6.22.0"
+    babel-plugin-transform-es2015-destructuring "^6.23.0"
+    babel-plugin-transform-es2015-duplicate-keys "^6.22.0"
+    babel-plugin-transform-es2015-for-of "^6.23.0"
+    babel-plugin-transform-es2015-function-name "^6.22.0"
+    babel-plugin-transform-es2015-literals "^6.22.0"
+    babel-plugin-transform-es2015-modules-amd "^6.22.0"
+    babel-plugin-transform-es2015-modules-commonjs "^6.23.0"
+    babel-plugin-transform-es2015-modules-systemjs "^6.23.0"
+    babel-plugin-transform-es2015-modules-umd "^6.23.0"
+    babel-plugin-transform-es2015-object-super "^6.22.0"
+    babel-plugin-transform-es2015-parameters "^6.23.0"
+    babel-plugin-transform-es2015-shorthand-properties "^6.22.0"
+    babel-plugin-transform-es2015-spread "^6.22.0"
+    babel-plugin-transform-es2015-sticky-regex "^6.22.0"
+    babel-plugin-transform-es2015-template-literals "^6.22.0"
+    babel-plugin-transform-es2015-typeof-symbol "^6.23.0"
+    babel-plugin-transform-es2015-unicode-regex "^6.22.0"
+    babel-plugin-transform-exponentiation-operator "^6.22.0"
+    babel-plugin-transform-regenerator "^6.22.0"
+    browserslist "^2.1.2"
+    invariant "^2.2.2"
+    semver "^5.3.0"
+
+babel-preset-es2015@6.24.1:
   version "6.24.1"
   resolved "https://registry.yarnpkg.com/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz#d44050d6bc2c9feea702aaf38d727a0210538939"
   dependencies:
@@ -924,11 +1189,31 @@ babel-preset-es2015@~6.24.1:
     babel-plugin-transform-es2015-unicode-regex "^6.24.1"
     babel-plugin-transform-regenerator "^6.24.1"
 
-babel-preset-jest@^20.0.3:
-  version "20.0.3"
-  resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-20.0.3.tgz#cbacaadecb5d689ca1e1de1360ebfc66862c178a"
+babel-preset-jest@^21.2.0:
+  version "21.2.0"
+  resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-21.2.0.tgz#ff9d2bce08abd98e8a36d9a8a5189b9173b85638"
   dependencies:
-    babel-plugin-jest-hoist "^20.0.3"
+    babel-plugin-jest-hoist "^21.2.0"
+    babel-plugin-syntax-object-rest-spread "^6.13.0"
+
+babel-preset-stage-2@6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz#d9e2960fb3d71187f0e64eec62bc07767219bdc1"
+  dependencies:
+    babel-plugin-syntax-dynamic-import "^6.18.0"
+    babel-plugin-transform-class-properties "^6.24.1"
+    babel-plugin-transform-decorators "^6.24.1"
+    babel-preset-stage-3 "^6.24.1"
+
+babel-preset-stage-3@^6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz#836ada0a9e7a7fa37cb138fb9326f87934a48395"
+  dependencies:
+    babel-plugin-syntax-trailing-function-commas "^6.22.0"
+    babel-plugin-transform-async-generator-functions "^6.24.1"
+    babel-plugin-transform-async-to-generator "^6.24.1"
+    babel-plugin-transform-exponentiation-operator "^6.24.1"
+    babel-plugin-transform-object-rest-spread "^6.22.0"
 
 babel-register@^6.24.1:
   version "6.24.1"
@@ -1042,10 +1327,6 @@ babylon@^6.18.0:
   version "6.18.0"
   resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3"
 
-backo2@1.0.2:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947"
-
 backoff@^2.5.0:
   version "2.5.0"
   resolved "https://registry.yarnpkg.com/backoff/-/backoff-2.5.0.tgz#f616eda9d3e4b66b8ca7fca79f695722c5f8e26f"
@@ -1056,10 +1337,6 @@ balanced-match@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
 
-base64-arraybuffer@0.1.5:
-  version "0.1.5"
-  resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz#73926771923b5a19747ad666aa5cd4bf9c6e9ce8"
-
 base64-img@^1.0.3:
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/base64-img/-/base64-img-1.0.3.tgz#a8c0284900047103421e1f9e0214011333866806"
@@ -1071,10 +1348,6 @@ base64-js@^1.2.0:
   version "1.2.1"
   resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.2.1.tgz#a91947da1f4a516ea38e5b4ec0ec3773675e0886"
 
-base64id@1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/base64id/-/base64id-1.0.0.tgz#47688cb99bb6804f0e06d3e763b1c32e57d8e6b6"
-
 base64url@2.0.0, base64url@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/base64url/-/base64url-2.0.0.tgz#eac16e03ea1438eff9423d69baa36262ed1f70bb"
@@ -1085,7 +1358,7 @@ bcrypt-pbkdf@^1.0.0:
   dependencies:
     tweetnacl "^0.14.3"
 
-bcryptjs-then@~1.0.1:
+bcryptjs-then@1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/bcryptjs-then/-/bcryptjs-then-1.0.1.tgz#0c03b22a5032dec7e25109faa6ce425eb5015158"
   dependencies:
@@ -1096,12 +1369,6 @@ bcryptjs@^2.3.0, bcryptjs@^2.4.0:
   version "2.4.3"
   resolved "https://registry.yarnpkg.com/bcryptjs/-/bcryptjs-2.4.3.tgz#9ab5627b93e60621ff7cdac5da9733027df1d0cb"
 
-better-assert@~1.0.0:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/better-assert/-/better-assert-1.0.2.tgz#40866b9e1b9e0b55b481894311e68faffaebc522"
-  dependencies:
-    callsite "1.0.0"
-
 bignumber.js@^2.1.0:
   version "2.4.0"
   resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-2.4.0.tgz#838a992da9f9d737e0f4b2db0be62bb09dd0c5e8"
@@ -1110,35 +1377,25 @@ binary-extensions@^1.0.0:
   version "1.8.0"
   resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.8.0.tgz#48ec8d16df4377eae5fa5884682480af4d95c774"
 
-bindings@~1.2.1:
-  version "1.2.1"
-  resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.2.1.tgz#14ad6113812d2d37d72e67b4cacb4bb726505f11"
-
-bl@^1.0.0:
-  version "1.2.1"
-  resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.1.tgz#cac328f7bee45730d404b692203fcb590e172d5e"
-  dependencies:
-    readable-stream "^2.0.5"
+bisection@:
+  version "0.0.3"
+  resolved "https://registry.yarnpkg.com/bisection/-/bisection-0.0.3.tgz#9891d506d86ec7d50910c5157bb592dbb03f33db"
 
 blessed@^0.1.81:
   version "0.1.81"
   resolved "https://registry.yarnpkg.com/blessed/-/blessed-0.1.81.tgz#f962d687ec2c369570ae71af843256e6d0ca1129"
 
-blob@0.0.4:
-  version "0.0.4"
-  resolved "https://registry.yarnpkg.com/blob/-/blob-0.0.4.tgz#bcf13052ca54463f30f9fc7e95b9a47630a94921"
-
 block-stream@*:
   version "0.0.9"
   resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a"
   dependencies:
     inherits "~2.0.0"
 
-bluebird@2.10.2:
-  version "2.10.2"
-  resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-2.10.2.tgz#024a5517295308857f14f91f1106fc3b555f446b"
+bluebird@3.5.1:
+  version "3.5.1"
+  resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9"
 
-bluebird@^3.0, bluebird@^3.1.1, bluebird@^3.4.1, bluebird@~3.5.0:
+bluebird@^3.1.1, bluebird@^3.3.4, bluebird@^3.4.1, bluebird@^3.4.6, bluebird@^3.5.0:
   version "3.5.0"
   resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.0.tgz#791420d7f551eea2897453a8a77653f96606d67c"
 
@@ -1146,7 +1403,22 @@ bmp-js@0.0.3:
   version "0.0.3"
   resolved "https://registry.yarnpkg.com/bmp-js/-/bmp-js-0.0.3.tgz#64113e9c7cf1202b376ed607bf30626ebe57b18a"
 
-body-parser@^1.14.2, body-parser@~1.17.2:
+body-parser@1.18.2:
+  version "1.18.2"
+  resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.2.tgz#87678a19d84b47d859b83199bd59bce222b10454"
+  dependencies:
+    bytes "3.0.0"
+    content-type "~1.0.4"
+    debug "2.6.9"
+    depd "~1.1.1"
+    http-errors "~1.6.2"
+    iconv-lite "0.4.19"
+    on-finished "~2.3.0"
+    qs "6.5.1"
+    raw-body "2.3.2"
+    type-is "~1.6.15"
+
+body-parser@^1.14.2:
   version "1.17.2"
   resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.17.2.tgz#f8892abc8f9e627d42aedafbca66bf5ab99104ee"
   dependencies:
@@ -1171,6 +1443,30 @@ boom@2.x.x:
   dependencies:
     hoek "2.x.x"
 
+boom@4.x.x:
+  version "4.3.1"
+  resolved "https://registry.yarnpkg.com/boom/-/boom-4.3.1.tgz#4f8a3005cb4a7e3889f749030fd25b96e01d2e31"
+  dependencies:
+    hoek "4.x.x"
+
+boom@5.x.x:
+  version "5.2.0"
+  resolved "https://registry.yarnpkg.com/boom/-/boom-5.2.0.tgz#5dd9da6ee3a5f302077436290cb717d3f4a54e02"
+  dependencies:
+    hoek "4.x.x"
+
+boxen@^1.0.0:
+  version "1.2.1"
+  resolved "https://registry.yarnpkg.com/boxen/-/boxen-1.2.1.tgz#0f11e7fe344edb9397977fc13ede7f64d956481d"
+  dependencies:
+    ansi-align "^2.0.0"
+    camelcase "^4.0.0"
+    chalk "^2.0.1"
+    cli-boxes "^1.0.0"
+    string-width "^2.0.0"
+    term-size "^1.2.0"
+    widest-line "^1.0.0"
+
 brace-expansion@^1.1.7:
   version "1.1.8"
   resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292"
@@ -1178,7 +1474,7 @@ brace-expansion@^1.1.7:
     balanced-match "^1.0.0"
     concat-map "0.0.1"
 
-brace@~0.10.0:
+brace@0.10.0:
   version "0.10.0"
   resolved "https://registry.yarnpkg.com/brace/-/brace-0.10.0.tgz#edef4eb9b0928ba1ee5f717ffc157749a6dd5d76"
   dependencies:
@@ -1198,11 +1494,12 @@ browser-resolve@^1.11.2:
   dependencies:
     resolve "1.1.7"
 
-bser@1.0.2:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/bser/-/bser-1.0.2.tgz#381116970b2a6deea5646dd15dd7278444b56169"
+browserslist@^2.1.2, browserslist@^2.5.0:
+  version "2.5.0"
+  resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-2.5.0.tgz#0ea00d22813a4dfae5786485225a9c584b3ef37c"
   dependencies:
-    node-int64 "^0.4.0"
+    caniuse-lite "^1.0.30000744"
+    electron-to-chromium "^1.3.24"
 
 bser@^2.0.0:
   version "2.0.0"
@@ -1210,10 +1507,6 @@ bser@^2.0.0:
   dependencies:
     node-int64 "^0.4.0"
 
-bson@~1.0.4:
-  version "1.0.4"
-  resolved "https://registry.yarnpkg.com/bson/-/bson-1.0.4.tgz#93c10d39eaa5b58415cbc4052f3e53e562b0b72c"
-
 buffer-equal-constant-time@1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819"
@@ -1222,26 +1515,38 @@ buffer-equal@0.0.1:
   version "0.0.1"
   resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-0.0.1.tgz#91bc74b11ea405bc916bc6aa908faafa5b4aac4b"
 
-buffer-shims@~1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/buffer-shims/-/buffer-shims-1.0.0.tgz#9978ce317388c649ad8793028c3477ef044a8b51"
+buffer-writer@1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/buffer-writer/-/buffer-writer-1.0.1.tgz#22a936901e3029afcd7547eb4487ceb697a3bf08"
 
 builtin-modules@^1.0.0, builtin-modules@^1.1.1:
   version "1.1.1"
   resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f"
 
-bunyan@^1.8.1, bunyan@^1.8.10, bunyan@^1.8.3:
-  version "1.8.10"
-  resolved "https://registry.yarnpkg.com/bunyan/-/bunyan-1.8.10.tgz#201fedd26c7080b632f416072f53a90b9a52981c"
+bull@3.3.0:
+  version "3.3.0"
+  resolved "https://registry.yarnpkg.com/bull/-/bull-3.3.0.tgz#79fc48f0ab6c63cc10fc053adfec4ddcbbc5dd44"
+  dependencies:
+    bluebird "^3.5.0"
+    cron-parser "^2.4.1"
+    debuglog "^1.0.0"
+    ioredis "^3.1.4"
+    lodash "^4.17.4"
+    semver "^5.4.1"
+    uuid "^3.1.0"
+
+bunyan@1.8.12:
+  version "1.8.12"
+  resolved "https://registry.yarnpkg.com/bunyan/-/bunyan-1.8.12.tgz#f150f0f6748abdd72aeae84f04403be2ef113797"
   optionalDependencies:
     dtrace-provider "~0.8"
     moment "^2.10.6"
     mv "~2"
     safe-json-stringify "~1"
 
-bunyan@~1.8.12:
-  version "1.8.12"
-  resolved "https://registry.yarnpkg.com/bunyan/-/bunyan-1.8.12.tgz#f150f0f6748abdd72aeae84f04403be2ef113797"
+bunyan@^1.8.3:
+  version "1.8.10"
+  resolved "https://registry.yarnpkg.com/bunyan/-/bunyan-1.8.10.tgz#201fedd26c7080b632f416072f53a90b9a52981c"
   optionalDependencies:
     dtrace-provider "~0.8"
     moment "^2.10.6"
@@ -1259,9 +1564,9 @@ bytes@2.4.0:
   version "2.4.0"
   resolved "https://registry.yarnpkg.com/bytes/-/bytes-2.4.0.tgz#7d97196f9d5baf7f6935e25985549edd2a6c2339"
 
-bytes@2.5.0:
-  version "2.5.0"
-  resolved "https://registry.yarnpkg.com/bytes/-/bytes-2.5.0.tgz#4c9423ea2d252c270c41b2bdefeff9bb6b62c06a"
+bytes@3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048"
 
 caller-path@^0.1.0:
   version "0.1.0"
@@ -1269,10 +1574,6 @@ caller-path@^0.1.0:
   dependencies:
     callsites "^0.2.0"
 
-callsite@1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/callsite/-/callsite-1.0.0.tgz#280398e5d664bd74038b6f0905153e6e8af1bc20"
-
 callsites@^0.2.0:
   version "0.2.0"
   resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca"
@@ -1300,10 +1601,18 @@ camelcase@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a"
 
-camelcase@^4.1.0:
+camelcase@^4.0.0, camelcase@^4.1.0:
   version "4.1.0"
   resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd"
 
+caniuse-lite@^1.0.30000744:
+  version "1.0.30000744"
+  resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000744.tgz#860fa5c83ba34fe619397d607f30bb474821671b"
+
+capture-stack-trace@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz#4a6fa07399c26bba47f0b2496b4d0fb408c5550d"
+
 caseless@~0.12.0:
   version "0.12.0"
   resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
@@ -1359,7 +1668,7 @@ charm@~0.1.1:
   version "0.1.2"
   resolved "https://registry.yarnpkg.com/charm/-/charm-0.1.2.tgz#06c21eed1a1b06aeb67553cdc53e23274bac2296"
 
-cheerio@~1.0.0-rc.2:
+cheerio@1.0.0-rc.2:
   version "1.0.0-rc.2"
   resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.2.tgz#4b9f53a81b27e4d5dac31c0ffd0cfa03cc6830db"
   dependencies:
@@ -1370,13 +1679,7 @@ cheerio@~1.0.0-rc.2:
     lodash "^4.15.0"
     parse5 "^3.0.1"
 
-child-process-promise@^1.1.0:
-  version "1.1.0"
-  resolved "https://registry.yarnpkg.com/child-process-promise/-/child-process-promise-1.1.0.tgz#131e01a705f15ed4a05d554dd5e032e52612cf30"
-  dependencies:
-    q "^1.1.2"
-
-child-process-promise@~2.2.1:
+child-process-promise@2.2.1:
   version "2.2.1"
   resolved "https://registry.yarnpkg.com/child-process-promise/-/child-process-promise-2.2.1.tgz#4730a11ef610fad450b8f223c79d31d7bdad8074"
   dependencies:
@@ -1384,7 +1687,13 @@ child-process-promise@~2.2.1:
     node-version "^1.0.0"
     promise-polyfill "^6.0.1"
 
-chokidar@^1.4.3, chokidar@^1.6.1, chokidar@^1.7, chokidar@~1.7.0:
+child-process-promise@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/child-process-promise/-/child-process-promise-1.1.0.tgz#131e01a705f15ed4a05d554dd5e032e52612cf30"
+  dependencies:
+    q "^1.1.2"
+
+chokidar@1.7.0, chokidar@^1.6.1, chokidar@^1.7, chokidar@^1.7.0:
   version "1.7.0"
   resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468"
   dependencies:
@@ -1418,6 +1727,10 @@ clean-css@^3.3.0:
     commander "2.8.x"
     source-map "0.4.x"
 
+cli-boxes@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-1.0.0.tgz#4fa917c3e59c94a004cd61f8ee509da651687143"
+
 cli-cursor@^2.1.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5"
@@ -1462,11 +1775,16 @@ cliui@^3.2.0:
     strip-ansi "^3.0.1"
     wrap-ansi "^2.0.0"
 
-closure-compiler@0.2.12:
-  version "0.2.12"
-  resolved "https://registry.yarnpkg.com/closure-compiler/-/closure-compiler-0.2.12.tgz#6c3087cad12742c79e47f0ce50e87af91cf8e171"
+cls-bluebird@^2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/cls-bluebird/-/cls-bluebird-2.0.1.tgz#c259a480ae02c0e506134307bb13db30446ee2e7"
   dependencies:
-    google-closure-compiler "20150901.x"
+    is-bluebird "^1.0.2"
+    shimmer "^1.1.0"
+
+cluster-key-slot@^1.0.6:
+  version "1.0.8"
+  resolved "https://registry.yarnpkg.com/cluster-key-slot/-/cluster-key-slot-1.0.8.tgz#7654556085a65330932a2e8b5976f8e2d0b3e414"
 
 co@^4.6.0:
   version "4.6.0"
@@ -1486,7 +1804,7 @@ codemirror@*:
   version "5.27.4"
   resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.27.4.tgz#0e817c839bfea9959dd16cd48ae14acc0e43c3b6"
 
-color-convert@^1.0.0:
+color-convert@^1.0.0, color-convert@^1.9.0:
   version "1.9.0"
   resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.0.tgz#1accf97dd739b983bf994d56fec8f95853641b7a"
   dependencies:
@@ -1500,7 +1818,7 @@ colors@1.0.x:
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b"
 
-colors@~1.1.2:
+colors@1.1.2:
   version "1.1.2"
   resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63"
 
@@ -1511,21 +1829,21 @@ combined-stream@^1.0.5, combined-stream@~1.0.5:
     delayed-stream "~1.0.0"
 
 command-line-args@^4.0.6:
-  version "4.0.7"
-  resolved "https://registry.yarnpkg.com/command-line-args/-/command-line-args-4.0.7.tgz#f8d1916ecb90e9e121eda6428e41300bfb64cc46"
+  version "4.0.6"
+  resolved "https://registry.yarnpkg.com/command-line-args/-/command-line-args-4.0.6.tgz#0ff87a1dd159890dcaeb2a005abdae71e55059fc"
   dependencies:
-    array-back "^2.0.0"
+    array-back "^1.0.4"
     find-replace "^1.0.3"
     typical "^2.6.1"
 
 command-line-usage@^4.0.0:
-  version "4.0.1"
-  resolved "https://registry.yarnpkg.com/command-line-usage/-/command-line-usage-4.0.1.tgz#d89cf16c8ae71e8e8a6e6aabae1652af76ff644e"
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/command-line-usage/-/command-line-usage-4.0.0.tgz#816b32788b58f9feba44d1e6dac60fcaeb29b5ea"
   dependencies:
-    ansi-escape-sequences "^4.0.0"
-    array-back "^2.0.0"
-    table-layout "^0.4.1"
-    typical "^2.6.1"
+    ansi-escape-sequences "^3.0.0"
+    array-back "^1.0.4"
+    table-layout "^0.4.0"
+    typical "^2.6.0"
 
 commander@2.11.0, commander@^2.11.0, commander@^2.9.0, commander@~2.11.0:
   version "2.11.0"
@@ -1537,35 +1855,23 @@ commander@2.8.x:
   dependencies:
     graceful-readlink ">= 1.0.0"
 
-component-bind@1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/component-bind/-/component-bind-1.0.0.tgz#00c608ab7dcd93897c0009651b1d3a8e1e73bbd1"
-
-component-emitter@1.2.1:
-  version "1.2.1"
-  resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6"
-
-component-inherit@0.0.3:
-  version "0.0.3"
-  resolved "https://registry.yarnpkg.com/component-inherit/-/component-inherit-0.0.3.tgz#645fc4adf58b72b649d5cae65135619db26ff143"
-
-compressible@~2.0.10:
-  version "2.0.10"
-  resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.10.tgz#feda1c7f7617912732b29bf8cf26252a20b9eecd"
+compressible@~2.0.11:
+  version "2.0.11"
+  resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.11.tgz#16718a75de283ed8e604041625a2064586797d8a"
   dependencies:
-    mime-db ">= 1.27.0 < 2"
+    mime-db ">= 1.29.0 < 2"
 
-compression@~1.7.0:
-  version "1.7.0"
-  resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.0.tgz#030c9f198f1643a057d776a738e922da4373012d"
+compression@1.7.1:
+  version "1.7.1"
+  resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.1.tgz#eff2603efc2e22cf86f35d2eb93589f9875373db"
   dependencies:
-    accepts "~1.3.3"
-    bytes "2.5.0"
-    compressible "~2.0.10"
-    debug "2.6.8"
+    accepts "~1.3.4"
+    bytes "3.0.0"
+    compressible "~2.0.11"
+    debug "2.6.9"
     on-headers "~1.0.1"
     safe-buffer "5.1.1"
-    vary "~1.1.1"
+    vary "~1.1.2"
 
 concat-map@0.0.1:
   version "0.0.1"
@@ -1592,35 +1898,33 @@ config-chain@^1.1.10:
     ini "^1.3.4"
     proto-list "~1.2.1"
 
-configstore@^1.0.0:
-  version "1.4.0"
-  resolved "https://registry.yarnpkg.com/configstore/-/configstore-1.4.0.tgz#c35781d0501d268c25c54b8b17f6240e8a4fb021"
+configstore@^3.0.0:
+  version "3.1.1"
+  resolved "https://registry.yarnpkg.com/configstore/-/configstore-3.1.1.tgz#094ee662ab83fad9917678de114faaea8fcdca90"
   dependencies:
+    dot-prop "^4.1.0"
     graceful-fs "^4.1.2"
-    mkdirp "^0.5.0"
-    object-assign "^4.0.1"
-    os-tmpdir "^1.0.0"
-    osenv "^0.1.0"
-    uuid "^2.0.1"
-    write-file-atomic "^1.1.2"
-    xdg-basedir "^2.0.0"
+    make-dir "^1.0.0"
+    unique-string "^1.0.0"
+    write-file-atomic "^2.0.0"
+    xdg-basedir "^3.0.0"
 
-connect-flash@~0.1.1:
+connect-flash@0.1.1:
   version "0.1.1"
   resolved "https://registry.yarnpkg.com/connect-flash/-/connect-flash-0.1.1.tgz#d8630f26d95a7f851f9956b1e8cc6732f3b6aa30"
 
-connect-mongo@~1.3.2:
-  version "1.3.2"
-  resolved "https://registry.yarnpkg.com/connect-mongo/-/connect-mongo-1.3.2.tgz#7cbf58dfff26760e5e00e017d0a85b4bc90b9d37"
+connect-redis@3.3.2:
+  version "3.3.2"
+  resolved "https://registry.yarnpkg.com/connect-redis/-/connect-redis-3.3.2.tgz#3706f9bfef1ec9b5d11c4b35b265de42c218b408"
   dependencies:
-    bluebird "^3.0"
-    mongodb ">= 1.2.0 <3.0.0"
+    debug "^3.1.0"
+    redis "^2.1.0"
 
 console-control-strings@^1.0.0, console-control-strings@~1.1.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e"
 
-consolidate@~0.14.5:
+consolidate@0.14.5:
   version "0.14.5"
   resolved "https://registry.yarnpkg.com/consolidate/-/consolidate-0.14.5.tgz#5a25047bc76f73072667c8cb52c989888f494c63"
   dependencies:
@@ -1653,6 +1957,10 @@ content-type@~1.0.1, content-type@~1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.2.tgz#b7d113aee7a8dd27bd21133c4dc2529df1721eed"
 
+content-type@~1.0.4:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
+
 continuation-local-storage@^3.1.4:
   version "3.2.0"
   resolved "https://registry.yarnpkg.com/continuation-local-storage/-/continuation-local-storage-3.2.0.tgz#e19fc36b597090a5d4e4a3b2ea3ebc5e29694a24"
@@ -1664,7 +1972,7 @@ convert-source-map@^1.1.0, convert-source-map@^1.4.0, convert-source-map@^1.5.0:
   version "1.5.0"
   resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.0.tgz#9acd70851c6d5dfdd93d9282e5edf94a03ff46b5"
 
-cookie-parser@~1.4.3:
+cookie-parser@1.4.3:
   version "1.4.3"
   resolved "https://registry.yarnpkg.com/cookie-parser/-/cookie-parser-1.4.3.tgz#0fe31fa19d000b95f4aadf1f53fdc2b8a203baa5"
   dependencies:
@@ -1687,20 +1995,20 @@ cookie@^0.2.3:
   version "0.2.4"
   resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.2.4.tgz#a8c155aa7b9b2cf2c4d32ebc7b9a0aa288ccc6bd"
 
-cookies@0.6.1:
-  version "0.6.1"
-  resolved "https://registry.yarnpkg.com/cookies/-/cookies-0.6.1.tgz#ef693b1bc6f01f567d46e2f504e9c15fb70cba90"
+cookies@0.7.1:
+  version "0.7.1"
+  resolved "https://registry.yarnpkg.com/cookies/-/cookies-0.7.1.tgz#7c8a615f5481c61ab9f16c833731bcb8f663b99b"
   dependencies:
-    depd "~1.1.0"
-    keygrip "~1.0.0"
+    depd "~1.1.1"
+    keygrip "~1.0.2"
 
 core-js@^2.4.0:
   version "2.4.1"
   resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.4.1.tgz#4de911e667b0eae9124e34254b53aea6fc618d3e"
 
 core-js@^2.5.0:
-  version "2.5.1"
-  resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.1.tgz#ae6874dc66937789b80754ff5428df66819ca50b"
+  version "2.5.0"
+  resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.0.tgz#569c050918be6486b3837552028ae0466b717086"
 
 core-util-is@1.0.2, core-util-is@~1.0.0:
   version "1.0.2"
@@ -1717,7 +2025,20 @@ crc@3.4.4, crc@^3.4.0:
   version "3.4.4"
   resolved "https://registry.yarnpkg.com/crc/-/crc-3.4.4.tgz#9da1e980e3bd44fc5c93bf5ab3da3378d85e466b"
 
-cron@1.2.1, cron@~1.2.1:
+create-error-class@^3.0.0:
+  version "3.0.2"
+  resolved "https://registry.yarnpkg.com/create-error-class/-/create-error-class-3.0.2.tgz#06be7abef947a3f14a30fd610671d401bca8b7b6"
+  dependencies:
+    capture-stack-trace "^1.0.0"
+
+cron-parser@^2.4.1:
+  version "2.4.1"
+  resolved "https://registry.yarnpkg.com/cron-parser/-/cron-parser-2.4.1.tgz#022befce1af293e4d3144ff04c2cbd2edb491271"
+  dependencies:
+    is-nan "^1.2.1"
+    moment-timezone "^0.5.0"
+
+cron@1.2.1:
   version "1.2.1"
   resolved "https://registry.yarnpkg.com/cron/-/cron-1.2.1.tgz#3a86c09b41b8f261ac863a7cc85ea4735857eab2"
   dependencies:
@@ -1751,6 +2072,16 @@ cryptiles@2.x.x:
   dependencies:
     boom "2.x.x"
 
+cryptiles@3.x.x:
+  version "3.1.2"
+  resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-3.1.2.tgz#a89fbb220f5ce25ec56e8c4aa8a4fd7b5b0d29fe"
+  dependencies:
+    boom "5.x.x"
+
+crypto-random-string@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e"
+
 css-select@~1.2.0:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.2.0.tgz#2b3a110539c5355f1cd8d314623e870b121ec858"
@@ -1798,21 +2129,33 @@ de-indent@^1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d"
 
-debug@*, debug@2.6.8, debug@^2.1.1, debug@^2.1.2, debug@^2.2.0, debug@^2.4.5, debug@^2.6, debug@^2.6.3, debug@^2.6.8, debug@~2.6.4, debug@~2.6.6:
+debug@2.6.7:
+  version "2.6.7"
+  resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.7.tgz#92bad1f6d05bbb6bba22cca88bcd0ec894c2861e"
+  dependencies:
+    ms "2.0.0"
+
+debug@2.6.9, debug@^2.6.9:
+  version "2.6.9"
+  resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
+  dependencies:
+    ms "2.0.0"
+
+debug@^2.1.1, debug@^2.1.2, debug@^2.2.0, debug@^2.4.5, debug@^2.6.3, debug@^2.6.8:
   version "2.6.8"
   resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc"
   dependencies:
     ms "2.0.0"
 
-debug@2.3.3:
-  version "2.3.3"
-  resolved "https://registry.yarnpkg.com/debug/-/debug-2.3.3.tgz#40c453e67e6e13c901ddec317af8986cda9eff8c"
+debug@^3, debug@^3.0, debug@^3.0.1, debug@^3.1.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
   dependencies:
-    ms "0.7.2"
+    ms "2.0.0"
 
-debug@2.6.7:
-  version "2.6.7"
-  resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.7.tgz#92bad1f6d05bbb6bba22cca88bcd0ec894c2861e"
+debug@^3.0.0:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/debug/-/debug-3.0.1.tgz#0564c612b521dc92d9f2988f0549e34f9c98db64"
   dependencies:
     ms "2.0.0"
 
@@ -1822,6 +2165,10 @@ debug@~2.2.0:
   dependencies:
     ms "0.7.1"
 
+debuglog@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492"
+
 decamelize@^1.0.0, decamelize@^1.1.1, decamelize@^1.1.2:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
@@ -1832,14 +2179,10 @@ decompress-response@^3.2.0:
   dependencies:
     mimic-response "^1.0.0"
 
-deep-extend@~0.4.0:
+deep-extend@~0.4.0, deep-extend@~0.4.1:
   version "0.4.2"
   resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.2.tgz#48b699c27e334bf89f10892be432f6e4c7d34a7f"
 
-deep-extend@~0.5.0:
-  version "0.5.0"
-  resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.5.0.tgz#6ef4a09b05f98b0e358d6d93d4ca3caec6672803"
-
 deep-is@~0.1.3:
   version "0.1.3"
   resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
@@ -1850,11 +2193,12 @@ default-require-extensions@^1.0.0:
   dependencies:
     strip-bom "^2.0.0"
 
-deferred-leveldown@~1.2.1:
-  version "1.2.1"
-  resolved "https://registry.yarnpkg.com/deferred-leveldown/-/deferred-leveldown-1.2.1.tgz#5d25c3310f5fe909946f6240dc9f90dd109a71ef"
+define-properties@^1.1.1:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.2.tgz#83a73f2fea569898fb737193c8f873caf6d45c94"
   dependencies:
-    abstract-leveldown "~2.4.0"
+    foreach "^2.0.5"
+    object-keys "^1.0.8"
 
 del@^2.0.2:
   version "2.2.2"
@@ -1880,7 +2224,11 @@ delegates@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
 
-depd@1.1.0, depd@~1.1.0:
+denque@^1.1.0:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/denque/-/denque-1.1.1.tgz#10229c2b88eec1bd15ff82c5fde356e7beb6db9e"
+
+depd@1.1.0, depd@^1.1.0, depd@~1.1.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.0.tgz#e1bd82c6aab6ced965b97b88b17ed3e528ca18c3"
 
@@ -1888,6 +2236,10 @@ depd@1.1.1, depd@~1.1.1:
   version "1.1.1"
   resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.1.tgz#5783b4e1c459f06fa5ca27f991f3d06e7a310359"
 
+deprecated-decorator@^0.1.6:
+  version "0.1.6"
+  resolved "https://registry.yarnpkg.com/deprecated-decorator/-/deprecated-decorator-0.1.6.tgz#00966317b7a12fe92f3cc831f7583af329b86c37"
+
 destroy@~1.0.4:
   version "1.0.4"
   resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
@@ -1905,11 +2257,11 @@ dicer@0.2.5, dicer@^0.2.5:
     readable-stream "1.1.x"
     streamsearch "0.1.2"
 
-diff2html@~2.3.0:
-  version "2.3.0"
-  resolved "https://registry.yarnpkg.com/diff2html/-/diff2html-2.3.0.tgz#375fb0783ca8fa90307749399bc9c75eb7cf6580"
+diff2html@2.3.1:
+  version "2.3.1"
+  resolved "https://registry.yarnpkg.com/diff2html/-/diff2html-2.3.1.tgz#8bf7f351607826e217446163cab6da52c560e0ab"
   dependencies:
-    diff "^3.2.0"
+    diff "^3.3.1"
     hogan.js "^3.0.2"
     whatwg-fetch "^2.0.3"
 
@@ -1917,13 +2269,9 @@ diff@^3.2.0:
   version "3.3.0"
   resolved "https://registry.yarnpkg.com/diff/-/diff-3.3.0.tgz#056695150d7aa93237ca7e378ac3b1682b7963b9"
 
-docproc@^1.0.0:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/docproc/-/docproc-1.0.1.tgz#12f572e0f0eec1fa0985094e7042308f09a8e8d5"
-  dependencies:
-    pumpify "^1.3.5"
-    term-frequency "^0.0.15"
-    term-vector "^0.1.2"
+diff@^3.3.1:
+  version "3.3.1"
+  resolved "https://registry.yarnpkg.com/diff/-/diff-3.3.1.tgz#aa8567a6eed03c531fc89d3f711cd0e5259dec75"
 
 doctrine@1.5.0:
   version "1.5.0"
@@ -1982,6 +2330,24 @@ domutils@^1.5.1:
     dom-serializer "0"
     domelementtype "1"
 
+dot-prop@^4.1.0:
+  version "4.2.0"
+  resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.0.tgz#1f19e0c2e1aa0e32797c49799f2837ac6af69c57"
+  dependencies:
+    is-obj "^1.0.0"
+
+dotize@^0.2.0:
+  version "0.2.0"
+  resolved "https://registry.yarnpkg.com/dotize/-/dotize-0.2.0.tgz#69e52f4a2b13344c56ff23c703c3074a2d6e57c7"
+
+dottie@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/dottie/-/dottie-2.0.0.tgz#da191981c8b8d713ca0115d5898cf397c2f0ddd0"
+
+double-ended-queue@^2.1.0-0:
+  version "2.1.0-0"
+  resolved "https://registry.yarnpkg.com/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz#103d3527fd31528f40188130c841efdd78264e5c"
+
 dtrace-provider@^0.7.0:
   version "0.7.1"
   resolved "https://registry.yarnpkg.com/dtrace-provider/-/dtrace-provider-0.7.1.tgz#c06b308f2f10d5d5838aec9c571e5d588dc71d04"
@@ -2002,15 +2368,6 @@ duplexer@~0.1.1:
   version "0.1.1"
   resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1"
 
-duplexify@^3.1.2, duplexify@^3.2.0:
-  version "3.5.0"
-  resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.5.0.tgz#1aa773002e1578457e9d9d4a50b0ccaaebcbd604"
-  dependencies:
-    end-of-stream "1.0.0"
-    inherits "^2.0.1"
-    readable-stream "^2.0.0"
-    stream-shift "^1.0.0"
-
 eachr@^3.2.0:
   version "3.2.0"
   resolved "https://registry.yarnpkg.com/eachr/-/eachr-3.2.0.tgz#2c35e43ea086516f7997cf80b7aa64d55a4a4484"
@@ -2039,6 +2396,10 @@ ee-first@1.1.1:
   version "1.1.1"
   resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
 
+electron-to-chromium@^1.3.24:
+  version "1.3.24"
+  resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.24.tgz#9b7b88bb05ceb9fa016a177833cc2dde388f21b6"
+
 emitter-listener@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/emitter-listener/-/emitter-listener-1.0.1.tgz#b2499ea6e58230a52c268d5df261eecd9f10fe97"
@@ -2055,69 +2416,17 @@ encoding@^0.1.11:
   dependencies:
     iconv-lite "~0.4.13"
 
-end-of-stream@1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.0.0.tgz#d4596e702734a93e40e9af864319eabd99ff2f0e"
-  dependencies:
-    once "~1.3.0"
-
-end-of-stream@^1.0.0, end-of-stream@^1.1.0:
-  version "1.4.0"
-  resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.0.tgz#7a90d833efda6cfa6eac0f4949dbb0fad3a63206"
-  dependencies:
-    once "^1.4.0"
-
 end-of-stream@~1.1.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.1.0.tgz#e9353258baa9108965efc41cb0ef8ade2f3cfb07"
   dependencies:
     once "~1.3.0"
 
-engine.io-client@~3.1.0:
-  version "3.1.1"
-  resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-3.1.1.tgz#415a9852badb14fa008fa3ef1e31608db6761325"
-  dependencies:
-    component-emitter "1.2.1"
-    component-inherit "0.0.3"
-    debug "~2.6.4"
-    engine.io-parser "~2.1.1"
-    has-cors "1.1.0"
-    indexof "0.0.1"
-    parsejson "0.0.3"
-    parseqs "0.0.5"
-    parseuri "0.0.5"
-    ws "~2.3.1"
-    xmlhttprequest-ssl "1.5.3"
-    yeast "0.1.2"
-
-engine.io-parser@~2.1.0, engine.io-parser@~2.1.1:
-  version "2.1.1"
-  resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-2.1.1.tgz#e0fb3f0e0462f7f58bb77c1a52e9f5a7e26e4668"
-  dependencies:
-    after "0.8.2"
-    arraybuffer.slice "0.0.6"
-    base64-arraybuffer "0.1.5"
-    blob "0.0.4"
-    has-binary2 "~1.0.2"
-
-engine.io@~3.1.0:
-  version "3.1.0"
-  resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-3.1.0.tgz#5ca438e3ce9fdbc915c4a21c8dd9e1266706e57e"
-  dependencies:
-    accepts "1.3.3"
-    base64id "1.0.0"
-    cookie "0.3.1"
-    debug "~2.6.4"
-    engine.io-parser "~2.1.0"
-    ws "~2.3.1"
-  optionalDependencies:
-    uws "~0.14.4"
-
 entities@^1.1.1, entities@~1.1.1:
   version "1.1.1"
   resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0"
 
-errno@^0.1.4, errno@~0.1.1:
+errno@^0.1.4:
   version "0.1.4"
   resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.4.tgz#b896e23a9e5e8ba33871fc996abd3635fc9a1c7d"
   dependencies:
@@ -2129,11 +2438,7 @@ error-ex@^1.2.0:
   dependencies:
     is-arrayish "^0.2.1"
 
-es6-promise@3.2.1:
-  version "3.2.1"
-  resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-3.2.1.tgz#ec56233868032909207170c39448e24449dd1fc4"
-
-es6-promise@^3.0.2:
+es6-promise@^3.0.2, es6-promise@^3.3.1:
   version "3.3.1"
   resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-3.3.1.tgz#a08cdde84ccdbf34d027a1451bc91d4bcd28a613"
 
@@ -2160,7 +2465,11 @@ escodegen@^1.6.1, escodegen@^1.8.1:
   optionalDependencies:
     source-map "~0.2.0"
 
-eslint-config-standard@~10.2.1:
+eslint-config-requarks@1.0.7:
+  version "1.0.7"
+  resolved "https://registry.yarnpkg.com/eslint-config-requarks/-/eslint-config-requarks-1.0.7.tgz#d2f1495ace70d5c88961c8bec4741efddd03458a"
+
+eslint-config-standard@10.2.1:
   version "10.2.1"
   resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-10.2.1.tgz#c061e4d066f379dc17cd562c64e819b4dd454591"
 
@@ -2178,7 +2487,7 @@ eslint-module-utils@^2.1.1:
     debug "^2.6.8"
     pkg-dir "^1.0.0"
 
-eslint-plugin-import@~2.7.0:
+eslint-plugin-import@2.7.0:
   version "2.7.0"
   resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.7.0.tgz#21de33380b9efb55f5ef6d2e210ec0e07e7fa69f"
   dependencies:
@@ -2193,20 +2502,20 @@ eslint-plugin-import@~2.7.0:
     minimatch "^3.0.3"
     read-pkg-up "^2.0.0"
 
-eslint-plugin-node@~5.1.0:
-  version "5.1.1"
-  resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-5.1.1.tgz#a7ed956e780c22aef6afd1116005acd82f26eac6"
+eslint-plugin-node@5.2.0:
+  version "5.2.0"
+  resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-5.2.0.tgz#e1efca04a385516cff3f2f04027ce8c5ae6db749"
   dependencies:
     ignore "^3.3.3"
     minimatch "^3.0.4"
     resolve "^1.3.3"
     semver "5.3.0"
 
-eslint-plugin-promise@~3.5.0:
+eslint-plugin-promise@3.5.0:
   version "3.5.0"
   resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-3.5.0.tgz#78fbb6ffe047201627569e85a6c5373af2a68fca"
 
-eslint-plugin-standard@~3.0.1:
+eslint-plugin-standard@3.0.1:
   version "3.0.1"
   resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-3.0.1.tgz#34d0c915b45edc6f010393c7eef3823b08565cf2"
 
@@ -2217,19 +2526,19 @@ eslint-scope@^3.7.1:
     esrecurse "^4.1.0"
     estraverse "^4.1.1"
 
-eslint@~4.5.0:
-  version "4.5.0"
-  resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.5.0.tgz#bb75d3b8bde97fb5e13efcd539744677feb019c3"
+eslint@4.8.0:
+  version "4.8.0"
+  resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.8.0.tgz#229ef0e354e0e61d837c7a80fdfba825e199815e"
   dependencies:
     ajv "^5.2.0"
     babel-code-frame "^6.22.0"
     chalk "^2.1.0"
     concat-stream "^1.6.0"
     cross-spawn "^5.1.0"
-    debug "^2.6.8"
+    debug "^3.0.1"
     doctrine "^2.0.0"
     eslint-scope "^3.7.1"
-    espree "^3.5.0"
+    espree "^3.5.1"
     esquery "^1.0.0"
     estraverse "^4.2.0"
     esutils "^2.0.2"
@@ -2250,7 +2559,7 @@ eslint@~4.5.0:
     natural-compare "^1.4.0"
     optionator "^0.8.2"
     path-is-inside "^1.0.2"
-    pluralize "^4.0.0"
+    pluralize "^7.0.0"
     progress "^2.0.0"
     require-uncached "^1.0.3"
     semver "^5.3.0"
@@ -2259,9 +2568,9 @@ eslint@~4.5.0:
     table "^4.0.1"
     text-table "~0.2.0"
 
-espree@^3.5.0:
-  version "3.5.0"
-  resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.0.tgz#98358625bdd055861ea27e2867ea729faf463d8d"
+espree@^3.5.1:
+  version "3.5.1"
+  resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.1.tgz#0c988b8ab46db53100a1954ae4ba995ddd27d87e"
   dependencies:
     acorn "^5.1.1"
     acorn-jsx "^3.0.0"
@@ -2307,6 +2616,10 @@ etag@~1.8.0:
   version "1.8.0"
   resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.0.tgz#6f631aef336d6c46362b51764044ce216be3c051"
 
+etag@~1.8.1:
+  version "1.8.1"
+  resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
+
 event-stream@~3.3.0:
   version "3.3.4"
   resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571"
@@ -2333,6 +2646,18 @@ exec-sh@^0.2.0:
   dependencies:
     merge "^1.1.3"
 
+execa@0.8.0:
+  version "0.8.0"
+  resolved "https://registry.yarnpkg.com/execa/-/execa-0.8.0.tgz#d8d76bbc1b55217ed190fd6dd49d3c774ecfc8da"
+  dependencies:
+    cross-spawn "^5.0.1"
+    get-stream "^3.0.0"
+    is-stream "^1.1.0"
+    npm-run-path "^2.0.0"
+    p-finally "^1.0.0"
+    signal-exit "^3.0.0"
+    strip-eof "^1.0.0"
+
 execa@^0.5.0:
   version "0.5.1"
   resolved "https://registry.yarnpkg.com/execa/-/execa-0.5.1.tgz#de3fb85cb8d6e91c85bcbceb164581785cb57b36"
@@ -2345,9 +2670,9 @@ execa@^0.5.0:
     signal-exit "^3.0.0"
     strip-eof "^1.0.0"
 
-execa@~0.8.0:
-  version "0.8.0"
-  resolved "https://registry.yarnpkg.com/execa/-/execa-0.8.0.tgz#d8d76bbc1b55217ed190fd6dd49d3c774ecfc8da"
+execa@^0.7.0:
+  version "0.7.0"
+  resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777"
   dependencies:
     cross-spawn "^5.0.1"
     get-stream "^3.0.0"
@@ -2373,17 +2698,24 @@ expand-range@^1.8.1:
   dependencies:
     fill-range "^2.1.0"
 
-expand-template@^1.0.2:
-  version "1.0.3"
-  resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-1.0.3.tgz#6c303323177a62b1b22c070279f7861287b69b1a"
-
-express-brute-mongoose@~0.0.9:
-  version "0.0.9"
-  resolved "https://registry.yarnpkg.com/express-brute-mongoose/-/express-brute-mongoose-0.0.9.tgz#7f8001c9548f78b705e6810be06f4c1e85745bd2"
+expect@^21.2.1:
+  version "21.2.1"
+  resolved "https://registry.yarnpkg.com/expect/-/expect-21.2.1.tgz#003ac2ac7005c3c29e73b38a272d4afadd6d1d7b"
   dependencies:
-    express-brute "~0.5.0"
-    moment "^2.18.1"
-    mongoose "*"
+    ansi-styles "^3.2.0"
+    jest-diff "^21.2.1"
+    jest-get-type "^21.2.0"
+    jest-matcher-utils "^21.2.1"
+    jest-message-util "^21.2.1"
+    jest-regex-util "^21.2.0"
+
+express-brute-redis@0.0.1:
+  version "0.0.1"
+  resolved "https://registry.yarnpkg.com/express-brute-redis/-/express-brute-redis-0.0.1.tgz#0f4c833a5c3c2505c0c5c9ba55108e224a247ef8"
+  dependencies:
+    express-brute "~0.4.2"
+    redis "~0.10.0"
+    underscore "~1.5.1"
 
 express-brute@1.0.1:
   version "1.0.1"
@@ -2392,25 +2724,61 @@ express-brute@1.0.1:
     long-timeout "~0.1.1"
     underscore "~1.8.3"
 
-express-brute@~0.5.0:
-  version "0.5.3"
-  resolved "https://registry.yarnpkg.com/express-brute/-/express-brute-0.5.3.tgz#0c8aabafe09dd722666587916f471b976f0c2a48"
+express-brute@~0.4.2:
+  version "0.4.2"
+  resolved "https://registry.yarnpkg.com/express-brute/-/express-brute-0.4.2.tgz#3bc34fb01252b8f47e737bf72dd01ff4df1d9c07"
   dependencies:
+    memcached "~0.2.4"
     underscore "~1.5.1"
 
-express-session@~1.15.5:
-  version "1.15.5"
-  resolved "https://registry.yarnpkg.com/express-session/-/express-session-1.15.5.tgz#f49a18227263b316f6f8544da5fee25a540259ec"
+express-session@1.15.6:
+  version "1.15.6"
+  resolved "https://registry.yarnpkg.com/express-session/-/express-session-1.15.6.tgz#47b4160c88f42ab70fe8a508e31cbff76757ab0a"
   dependencies:
     cookie "0.3.1"
     cookie-signature "1.0.6"
     crc "3.4.4"
-    debug "2.6.8"
+    debug "2.6.9"
     depd "~1.1.1"
     on-headers "~1.0.1"
-    parseurl "~1.3.1"
-    uid-safe "~2.1.4"
-    utils-merge "1.0.0"
+    parseurl "~1.3.2"
+    uid-safe "~2.1.5"
+    utils-merge "1.0.1"
+
+express@4.16.1:
+  version "4.16.1"
+  resolved "https://registry.yarnpkg.com/express/-/express-4.16.1.tgz#6b33b560183c9b253b7b62144df33a4654ac9ed0"
+  dependencies:
+    accepts "~1.3.4"
+    array-flatten "1.1.1"
+    body-parser "1.18.2"
+    content-disposition "0.5.2"
+    content-type "~1.0.4"
+    cookie "0.3.1"
+    cookie-signature "1.0.6"
+    debug "2.6.9"
+    depd "~1.1.1"
+    encodeurl "~1.0.1"
+    escape-html "~1.0.3"
+    etag "~1.8.1"
+    finalhandler "1.1.0"
+    fresh "0.5.2"
+    merge-descriptors "1.0.1"
+    methods "~1.1.2"
+    on-finished "~2.3.0"
+    parseurl "~1.3.2"
+    path-to-regexp "0.1.7"
+    proxy-addr "~2.0.2"
+    qs "6.5.1"
+    range-parser "~1.2.0"
+    safe-buffer "5.1.1"
+    send "0.16.1"
+    serve-static "1.13.1"
+    setprototypeof "1.1.0"
+    statuses "~1.3.1"
+    type-is "~1.6.15"
+    utils-merge "1.0.1"
+    vary "~1.1.2"
 
 express@^4.14.0:
   version "4.15.3"
@@ -2475,40 +2843,7 @@ express@~4.13.1:
     utils-merge "1.0.0"
     vary "~1.0.1"
 
-express@~4.15.4:
-  version "4.15.4"
-  resolved "https://registry.yarnpkg.com/express/-/express-4.15.4.tgz#032e2253489cf8fce02666beca3d11ed7a2daed1"
-  dependencies:
-    accepts "~1.3.3"
-    array-flatten "1.1.1"
-    content-disposition "0.5.2"
-    content-type "~1.0.2"
-    cookie "0.3.1"
-    cookie-signature "1.0.6"
-    debug "2.6.8"
-    depd "~1.1.1"
-    encodeurl "~1.0.1"
-    escape-html "~1.0.3"
-    etag "~1.8.0"
-    finalhandler "~1.0.4"
-    fresh "0.5.0"
-    merge-descriptors "1.0.1"
-    methods "~1.1.2"
-    on-finished "~2.3.0"
-    parseurl "~1.3.1"
-    path-to-regexp "0.1.7"
-    proxy-addr "~1.1.5"
-    qs "6.5.0"
-    range-parser "~1.2.0"
-    send "0.15.4"
-    serve-static "1.12.4"
-    setprototypeof "1.0.3"
-    statuses "~1.3.1"
-    type-is "~1.6.15"
-    utils-merge "1.0.0"
-    vary "~1.1.1"
-
-extend@^3.0.0, extend@~3.0.0:
+extend@^3.0.0, extend@~3.0.0, extend@~3.0.1:
   version "3.0.1"
   resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444"
 
@@ -2554,33 +2889,25 @@ fast-deep-equal@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff"
 
-fast-future@~1.0.2:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/fast-future/-/fast-future-1.0.2.tgz#8435a9aaa02d79248d17d704e76259301d99280a"
-
 fast-levenshtein@~2.0.4:
   version "2.0.6"
   resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
 
-fb-watchman@^1.8.0:
-  version "1.9.2"
-  resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-1.9.2.tgz#a24cf47827f82d38fb59a69ad70b76e3b6ae7383"
-  dependencies:
-    bser "1.0.2"
-
 fb-watchman@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.0.tgz#54e9abf7dfa2f26cd9b1636c588c1afc05de5d58"
   dependencies:
     bser "^2.0.0"
 
-fclone@1.0.11:
+fclone@1.0.11, fclone@^1:
   version "1.0.11"
   resolved "https://registry.yarnpkg.com/fclone/-/fclone-1.0.11.tgz#10e85da38bfea7fc599341c296ee1d77266ee640"
 
-fclone@1.0.8:
-  version "1.0.8"
-  resolved "https://registry.yarnpkg.com/fclone/-/fclone-1.0.8.tgz#a0d4a73d983249978c0e0671a161520b996467eb"
+feature-detect-es6@^1.3.1:
+  version "1.3.1"
+  resolved "https://registry.yarnpkg.com/feature-detect-es6/-/feature-detect-es6-1.3.1.tgz#f888736af9cb0c91f55663bfa4762eb96ee7047f"
+  dependencies:
+    array-back "^1.0.3"
 
 figures@^2.0.0:
   version "2.0.0"
@@ -2608,14 +2935,14 @@ file-system@^2.1.0, file-system@^2.1.1:
     file-match "^1.0.1"
     utils-extend "^1.0.4"
 
+file-type@6.2.0:
+  version "6.2.0"
+  resolved "https://registry.yarnpkg.com/file-type/-/file-type-6.2.0.tgz#e50cd75d356ffed4e306dc4f5bcf52a79903a919"
+
 file-type@^3.1.0:
   version "3.9.0"
   resolved "https://registry.yarnpkg.com/file-type/-/file-type-3.9.0.tgz#257a078384d1db8087bc449d107d52a52672b9e9"
 
-file-type@~6.1.0:
-  version "6.1.0"
-  resolved "https://registry.yarnpkg.com/file-type/-/file-type-6.1.0.tgz#5a7dba98138fa0abec7afc43e5a9a0b2aac729f1"
-
 filename-regex@^2.0.0:
   version "2.0.1"
   resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26"
@@ -2627,7 +2954,7 @@ fileset@^2.0.2:
     glob "^7.0.3"
     minimatch "^3.0.3"
 
-filesize.js@~1.0.2:
+filesize.js@1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/filesize.js/-/filesize.js-1.0.2.tgz#934c013395a71804875cf11e6f1ffe211c3f2192"
 
@@ -2650,6 +2977,18 @@ finalhandler@0.4.1:
     on-finished "~2.3.0"
     unpipe "~1.0.0"
 
+finalhandler@1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.0.tgz#ce0b6855b45853e791b2fcc680046d88253dd7f5"
+  dependencies:
+    debug "2.6.9"
+    encodeurl "~1.0.1"
+    escape-html "~1.0.3"
+    on-finished "~2.3.0"
+    parseurl "~1.3.2"
+    statuses "~1.3.1"
+    unpipe "~1.0.0"
+
 finalhandler@~1.0.3:
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.0.3.tgz#ef47e77950e999780e86022a560e3217e0d0cc89"
@@ -2662,18 +3001,6 @@ finalhandler@~1.0.3:
     statuses "~1.3.1"
     unpipe "~1.0.0"
 
-finalhandler@~1.0.4:
-  version "1.0.4"
-  resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.0.4.tgz#18574f2e7c4b98b8ae3b230c21f201f31bdb3fb7"
-  dependencies:
-    debug "2.6.8"
-    encodeurl "~1.0.1"
-    escape-html "~1.0.3"
-    on-finished "~2.3.0"
-    parseurl "~1.3.1"
-    statuses "~1.3.1"
-    unpipe "~1.0.0"
-
 find-line-column@^0.5.2:
   version "0.5.2"
   resolved "https://registry.yarnpkg.com/find-line-column/-/find-line-column-0.5.2.tgz#db00238ff868551a182e74a103416d295a98c8ca"
@@ -2707,13 +3034,27 @@ flat-cache@^1.2.1:
     graceful-fs "^4.1.2"
     write "^0.2.1"
 
+flatten@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782"
+
+flexbuffer@0.0.6:
+  version "0.0.6"
+  resolved "https://registry.yarnpkg.com/flexbuffer/-/flexbuffer-0.0.6.tgz#039fdf23f8823e440c38f3277e6fef1174215b30"
+
 fliplog@^0.3.13:
   version "0.3.13"
   resolved "https://registry.yarnpkg.com/fliplog/-/fliplog-0.3.13.tgz#dd0d786e821822aae272e0ddc84012596a96154c"
   dependencies:
     chain-able "^1.0.1"
 
-follow-redirects@^1.2.3, follow-redirects@~1.2.4:
+follow-redirects@1.2.5:
+  version "1.2.5"
+  resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.2.5.tgz#ffd3e14cbdd5eaa72f61b6368c1f68516c2a26cc"
+  dependencies:
+    debug "^2.6.9"
+
+follow-redirects@^1.2.3:
   version "1.2.4"
   resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.2.4.tgz#355e8f4d16876b43f577b0d5ce2668b9723214ea"
   dependencies:
@@ -2735,6 +3076,10 @@ for-own@^0.1.4:
   dependencies:
     for-in "^1.0.1"
 
+foreach@^2.0.5:
+  version "2.0.5"
+  resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99"
+
 forever-agent@~0.6.1:
   version "0.6.1"
   resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
@@ -2747,10 +3092,22 @@ form-data@~2.1.1:
     combined-stream "^1.0.5"
     mime-types "^2.1.12"
 
+form-data@~2.3.1:
+  version "2.3.1"
+  resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.1.tgz#6fb94fbd71885306d73d15cc497fe4cc4ecd44bf"
+  dependencies:
+    asynckit "^0.4.0"
+    combined-stream "^1.0.5"
+    mime-types "^2.1.12"
+
 forwarded@~0.1.0:
   version "0.1.0"
   resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.0.tgz#19ef9874c4ae1c297bcf078fde63a09b66a84363"
 
+forwarded@~0.1.2:
+  version "0.1.2"
+  resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84"
+
 fresh@0.3.0:
   version "0.3.0"
   resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.3.0.tgz#651f838e22424e7566de161d8358caa199f83d4f"
@@ -2759,10 +3116,22 @@ fresh@0.5.0:
   version "0.5.0"
   resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.0.tgz#f474ca5e6a9246d6fd8e0953cfa9b9c805afa78e"
 
+fresh@0.5.2:
+  version "0.5.2"
+  resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
+
 from@~0:
   version "0.1.7"
   resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe"
 
+fs-extra@4.0.2:
+  version "4.0.2"
+  resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.2.tgz#f91704c53d1b461f893452b0c307d9997647ab6b"
+  dependencies:
+    graceful-fs "^4.1.2"
+    jsonfile "^4.0.0"
+    universalify "^0.1.0"
+
 fs-extra@^2.0.0:
   version "2.1.2"
   resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-2.1.2.tgz#046c70163cef9aad46b0e4a7fa467fb22d71de35"
@@ -2770,14 +3139,6 @@ fs-extra@^2.0.0:
     graceful-fs "^4.1.2"
     jsonfile "^2.1.0"
 
-fs-extra@~4.0.1:
-  version "4.0.1"
-  resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.1.tgz#7fc0c6c8957f983f57f306a24e5b9ddd8d0dd880"
-  dependencies:
-    graceful-fs "^4.1.2"
-    jsonfile "^3.0.0"
-    universalify "^0.1.0"
-
 fs-readdir-recursive@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/fs-readdir-recursive/-/fs-readdir-recursive-1.0.0.tgz#8cd1745c8b4f8a29c8caec392476921ba195f560"
@@ -2786,7 +3147,7 @@ fs.realpath@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
 
-fsevents@^1.0.0:
+fsevents@^1.0.0, fsevents@^1.1.1:
   version "1.1.2"
   resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.1.2.tgz#3282b713fb3ad80ede0e9fcf4611b5aa6fc033f4"
   dependencies:
@@ -2818,14 +3179,15 @@ functional-red-black-tree@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327"
 
-fuse-box@~2.2.2:
-  version "2.2.2"
-  resolved "https://registry.yarnpkg.com/fuse-box/-/fuse-box-2.2.2.tgz#eec3c4c49496dbfca08d43179a189fbfbce67fda"
+fuse-box@2.3.3:
+  version "2.3.3"
+  resolved "https://registry.yarnpkg.com/fuse-box/-/fuse-box-2.3.3.tgz#0d3e551c7617f37886df75c57e67df6fe05ea0db"
   dependencies:
     acorn "^5.0.3"
     acorn-es7 "^0.1.0"
     acorn-es7-plugin "^1.1.7"
     acorn-jsx "^4.0.1"
+    acorn-object-rest-spread "^1.1.0"
     ansi "^0.3.1"
     app-root-path "^2.0.1"
     base64-img "^1.0.3"
@@ -2875,6 +3237,14 @@ gaze@^1.0.0:
   dependencies:
     globule "^1.0.0"
 
+generic-pool@2.4.3:
+  version "2.4.3"
+  resolved "https://registry.yarnpkg.com/generic-pool/-/generic-pool-2.4.3.tgz#780c36f69dfad05a5a045dd37be7adca11a4f6ff"
+
+generic-pool@^3.1.8:
+  version "3.1.8"
+  resolved "https://registry.yarnpkg.com/generic-pool/-/generic-pool-3.1.8.tgz#09844b6545bc9177ec218bd35d4ad894c65be271"
+
 get-caller-file@^1.0.1:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5"
@@ -2906,16 +3276,12 @@ getpass@^0.1.1:
   dependencies:
     assert-plus "^1.0.0"
 
-git-wrapper2-promise@~0.2.9:
+git-wrapper2-promise@0.2.9:
   version "0.2.9"
   resolved "https://registry.yarnpkg.com/git-wrapper2-promise/-/git-wrapper2-promise-0.2.9.tgz#2c781e26a16246b05eba45fa17df687403bbfd7d"
   dependencies:
     child-process-promise "^1.1.0"
 
-github-from-package@0.0.0:
-  version "0.0.0"
-  resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce"
-
 "gkt@https://tgz.pm2.io/gkt-1.0.0.tgz":
   version "1.0.0"
   resolved "https://tgz.pm2.io/gkt-1.0.0.tgz#405502b007f319c3f47175c4474527300f2ab5ad"
@@ -2933,17 +3299,6 @@ glob-parent@^2.0.0:
   dependencies:
     is-glob "^2.0.0"
 
-glob@7.1.1:
-  version "7.1.1"
-  resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8"
-  dependencies:
-    fs.realpath "^1.0.0"
-    inflight "^1.0.4"
-    inherits "2"
-    minimatch "^3.0.2"
-    once "^1.3.0"
-    path-is-absolute "^1.0.0"
-
 glob@^6.0.1:
   version "6.0.4"
   resolved "https://registry.yarnpkg.com/glob/-/glob-6.0.4.tgz#0f08860f6a155127b2fadd4f9ce24b1aab6e4d22"
@@ -3001,24 +3356,21 @@ good-listener@^1.2.2:
   dependencies:
     delegate "^3.1.2"
 
-google-closure-compiler@20150901.x:
-  version "20150901.0.0"
-  resolved "https://registry.yarnpkg.com/google-closure-compiler/-/google-closure-compiler-20150901.0.0.tgz#3d01c6cade65790a9bfb4e30b2158b7635acbade"
-
-got@^3.2.0:
-  version "3.3.1"
-  resolved "https://registry.yarnpkg.com/got/-/got-3.3.1.tgz#e5d0ed4af55fc3eef4d56007769d98192bcb2eca"
+got@^6.7.1:
+  version "6.7.1"
+  resolved "https://registry.yarnpkg.com/got/-/got-6.7.1.tgz#240cd05785a9a18e561dc1b44b41c763ef1e8db0"
   dependencies:
-    duplexify "^3.2.0"
-    infinity-agent "^2.0.0"
+    create-error-class "^3.0.0"
+    duplexer3 "^0.1.4"
+    get-stream "^3.0.0"
     is-redirect "^1.0.0"
+    is-retry-allowed "^1.0.0"
     is-stream "^1.0.0"
     lowercase-keys "^1.0.0"
-    nested-error-stacks "^1.0.0"
-    object-assign "^3.0.0"
-    prepend-http "^1.0.0"
-    read-all-stream "^3.0.0"
-    timed-out "^2.0.0"
+    safe-buffer "^5.0.1"
+    timed-out "^4.0.0"
+    unzip-response "^2.0.1"
+    url-parse-lax "^1.0.0"
 
 got@^7.0.0:
   version "7.1.0"
@@ -3047,6 +3399,45 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.4, graceful-fs@^4.1.6,
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725"
 
+graphql-anywhere@^3.0.1:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/graphql-anywhere/-/graphql-anywhere-3.1.0.tgz#3ea0d8e8646b5cee68035016a9a7557c15c21e96"
+
+graphql-tag@^2.0.0, graphql-tag@^2.4.2:
+  version "2.4.2"
+  resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.4.2.tgz#6a63297d8522d03a2b72d26f1b239aab343840cd"
+
+graphql-tools@2.2.1:
+  version "2.2.1"
+  resolved "https://registry.yarnpkg.com/graphql-tools/-/graphql-tools-2.2.1.tgz#ff4d73d3e52e09b38b3f2f4ed53c29d4baa122b1"
+  dependencies:
+    apollo-link "^0.7.0"
+    deprecated-decorator "^0.1.6"
+    uuid "^3.1.0"
+  optionalDependencies:
+    "@types/graphql" "^0.11.4"
+
+graphql-tools@^1.1.0:
+  version "1.2.1"
+  resolved "https://registry.yarnpkg.com/graphql-tools/-/graphql-tools-1.2.1.tgz#8d462abaa7b0f3bb2aa633df1e7a848720197671"
+  dependencies:
+    deprecated-decorator "^0.1.6"
+    uuid "^3.0.1"
+  optionalDependencies:
+    "@types/graphql" "^0.9.0"
+
+graphql@0.10.5, graphql@^0.10.0, graphql@^0.10.3:
+  version "0.10.5"
+  resolved "https://registry.yarnpkg.com/graphql/-/graphql-0.10.5.tgz#c9be17ca2bdfdbd134077ffd9bbaa48b8becd298"
+  dependencies:
+    iterall "^1.1.0"
+
+graphql@^0.11.3:
+  version "0.11.7"
+  resolved "https://registry.yarnpkg.com/graphql/-/graphql-0.11.7.tgz#e5abaa9cb7b7cccb84e9f0836bf4370d268750c6"
+  dependencies:
+    iterall "1.1.3"
+
 growly@^1.3.0:
   version "1.3.0"
   resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081"
@@ -3065,6 +3456,10 @@ har-schema@^1.0.5:
   version "1.0.5"
   resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-1.0.5.tgz#d263135f43307c02c602afc8fe95970c0151369e"
 
+har-schema@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
+
 har-validator@~4.2.1:
   version "4.2.1"
   resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-4.2.1.tgz#33481d0f1bbff600dd203d75812a6a5fba002e2a"
@@ -3072,22 +3467,19 @@ har-validator@~4.2.1:
     ajv "^4.9.1"
     har-schema "^1.0.5"
 
+har-validator@~5.0.3:
+  version "5.0.3"
+  resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.0.3.tgz#ba402c266194f15956ef15e0fcf242993f6a7dfd"
+  dependencies:
+    ajv "^5.1.0"
+    har-schema "^2.0.0"
+
 has-ansi@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91"
   dependencies:
     ansi-regex "^2.0.0"
 
-has-binary2@~1.0.2:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/has-binary2/-/has-binary2-1.0.2.tgz#e83dba49f0b9be4d026d27365350d9f03f54be98"
-  dependencies:
-    isarray "2.0.1"
-
-has-cors@1.1.0:
-  version "1.1.0"
-  resolved "https://registry.yarnpkg.com/has-cors/-/has-cors-1.1.0.tgz#5e474793f7ea9843d1bb99c23eef49ff126fff39"
-
 has-flag@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa"
@@ -3116,6 +3508,13 @@ has@^1.0.1:
   dependencies:
     function-bind "^1.0.2"
 
+hashring@0.0.x:
+  version "0.0.8"
+  resolved "https://registry.yarnpkg.com/hashring/-/hashring-0.0.8.tgz#203ab13c364119f10106526d2eaf7bd42b484c31"
+  dependencies:
+    bisection ""
+    simple-lru-cache "0.0.x"
+
 hawk@~3.1.3:
   version "3.1.3"
   resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4"
@@ -3125,11 +3524,20 @@ hawk@~3.1.3:
     hoek "2.x.x"
     sntp "1.x.x"
 
+hawk@~6.0.2:
+  version "6.0.2"
+  resolved "https://registry.yarnpkg.com/hawk/-/hawk-6.0.2.tgz#af4d914eb065f9b5ce4d9d11c1cb2126eecc3038"
+  dependencies:
+    boom "4.x.x"
+    cryptiles "3.x.x"
+    hoek "4.x.x"
+    sntp "2.x.x"
+
 he@^1.1.0:
   version "1.1.1"
   resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd"
 
-highlight.js@~9.12.0:
+highlight.js@9.12.0:
   version "9.12.0"
   resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.12.0.tgz#e6d9dbe57cbefe60751f02af336195870c90c01e"
 
@@ -3137,6 +3545,10 @@ hoek@2.x.x:
   version "2.16.3"
   resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed"
 
+hoek@4.x.x:
+  version "4.2.0"
+  resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.0.tgz#72d9d0754f7fe25ca2d01ad8f8f9a9449a89526d"
+
 hogan.js@^3.0.2:
   version "3.0.2"
   resolved "https://registry.yarnpkg.com/hogan.js/-/hogan.js-3.0.2.tgz#4cd9e1abd4294146e7679e41d7898732b02c7bfd"
@@ -3151,10 +3563,6 @@ home-or-tmp@^2.0.0:
     os-homedir "^1.0.0"
     os-tmpdir "^1.0.1"
 
-hooks-fixed@2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/hooks-fixed/-/hooks-fixed-2.0.0.tgz#a01d894d52ac7f6599bbb1f63dfc9c411df70cba"
-
 hosted-git-info@^2.1.4:
   version "2.5.0"
   resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.5.0.tgz#6d60e34b3abbc8313062c3b798ef8d901a07af3c"
@@ -3176,6 +3584,15 @@ htmlparser2@^3.9.1:
     inherits "^2.0.1"
     readable-stream "^2.0.2"
 
+http-errors@1.6.2, http-errors@~1.6.2:
+  version "1.6.2"
+  resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.2.tgz#0a002cc85707192a7e7946ceedc11155f60ec736"
+  dependencies:
+    depd "1.1.1"
+    inherits "2.0.3"
+    setprototypeof "1.0.3"
+    statuses ">= 1.3.1 < 2"
+
 http-errors@~1.3.1:
   version "1.3.1"
   resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.3.1.tgz#197e22cdebd4198585e8694ef6786197b91ed942"
@@ -3192,15 +3609,6 @@ http-errors@~1.6.1:
     setprototypeof "1.0.3"
     statuses ">= 1.3.1 < 2"
 
-http-errors@~1.6.2:
-  version "1.6.2"
-  resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.2.tgz#0a002cc85707192a7e7946ceedc11155f60ec736"
-  dependencies:
-    depd "1.1.1"
-    inherits "2.0.3"
-    setprototypeof "1.0.3"
-    statuses ">= 1.3.1 < 2"
-
 http-signature@~1.1.0:
   version "1.1.1"
   resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf"
@@ -3209,26 +3617,38 @@ http-signature@~1.1.0:
     jsprim "^1.2.2"
     sshpk "^1.7.0"
 
-i18next-express-middleware@~1.0.5:
-  version "1.0.5"
-  resolved "https://registry.yarnpkg.com/i18next-express-middleware/-/i18next-express-middleware-1.0.5.tgz#12dce7c553866e11c108943d46ce494baf982219"
+http-signature@~1.2.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1"
   dependencies:
-    cookies "0.6.1"
+    assert-plus "^1.0.0"
+    jsprim "^1.2.2"
+    sshpk "^1.7.0"
 
-i18next-node-fs-backend@~1.0.0:
+i18next-express-middleware@1.0.7:
+  version "1.0.7"
+  resolved "https://registry.yarnpkg.com/i18next-express-middleware/-/i18next-express-middleware-1.0.7.tgz#7909233f4e6e94b5bd4964a114247dc8d6f3f839"
+  dependencies:
+    cookies "0.7.1"
+
+i18next-localstorage-cache@1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/i18next-localstorage-cache/-/i18next-localstorage-cache-1.1.1.tgz#575256cc35e8cb2d88148f754766fdd2d24bb1b7"
+
+i18next-node-fs-backend@1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/i18next-node-fs-backend/-/i18next-node-fs-backend-1.0.0.tgz#f5a625a3b287c1d098c7171b7dd376bb07299b59"
   dependencies:
     js-yaml "3.5.4"
     json5 "0.5.0"
 
-i18next-xhr-backend@~1.4.2:
-  version "1.4.2"
-  resolved "https://registry.yarnpkg.com/i18next-xhr-backend/-/i18next-xhr-backend-1.4.2.tgz#7aa766292c46ca83ff6477bb55074b363a646a62"
+i18next-xhr-backend@1.4.3:
+  version "1.4.3"
+  resolved "https://registry.yarnpkg.com/i18next-xhr-backend/-/i18next-xhr-backend-1.4.3.tgz#d72f70536a3bf6a3892261dde352bc77d708886a"
 
-i18next@~9.0.0:
-  version "9.0.0"
-  resolved "https://registry.yarnpkg.com/i18next/-/i18next-9.0.0.tgz#a89ab0481b5b6b3964f55b12f03de9063d8f4500"
+i18next@9.1.0:
+  version "9.1.0"
+  resolved "https://registry.yarnpkg.com/i18next/-/i18next-9.1.0.tgz#408005fe262a990c8d93946a6de0c77bba11667b"
 
 iconv-lite@0.4.13:
   version "0.4.13"
@@ -3238,6 +3658,10 @@ iconv-lite@0.4.15:
   version "0.4.15"
   resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.15.tgz#fe265a218ac6a57cfe854927e9d04c19825eddeb"
 
+iconv-lite@0.4.19:
+  version "0.4.19"
+  resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b"
+
 iconv-lite@^0.4.17, iconv-lite@^0.4.4, iconv-lite@~0.4.13:
   version "0.4.18"
   resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.18.tgz#23d8656b16aae6742ac29732ea8f0336a4789cf2"
@@ -3246,7 +3670,7 @@ ieee754@^1.1.8:
   version "1.1.8"
   resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.8.tgz#be33d40ac10ef1926701f6f08a2d86fbfd1ad3e4"
 
-ignore-by-default@^1.0.0:
+ignore-by-default@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09"
 
@@ -3254,13 +3678,13 @@ ignore@^3.3.3:
   version "3.3.3"
   resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.3.tgz#432352e57accd87ab3110e82d3fea0e47812156d"
 
-image-size@~0.6.0:
+image-size@0.6.1:
   version "0.6.1"
   resolved "https://registry.yarnpkg.com/image-size/-/image-size-0.6.1.tgz#98122a562d59dcc097ef1b2c8191866eb8f5d663"
 
-immediate@^3.2.3:
-  version "3.2.3"
-  resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.2.3.tgz#d140fa8f614659bd6541233097ddaac25cdd991c"
+import-lazy@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43"
 
 imurmurhash@^0.1.4:
   version "0.1.4"
@@ -3276,13 +3700,13 @@ indent-string@^2.1.0:
   dependencies:
     repeating "^2.0.0"
 
-indexof@0.0.1:
-  version "0.0.1"
-  resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d"
+indexes-of@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607"
 
-infinity-agent@^2.0.0:
-  version "2.0.3"
-  resolved "https://registry.yarnpkg.com/infinity-agent/-/infinity-agent-2.0.3.tgz#45e0e2ff7a9eb030b27d62b74b3744b7a7ac4216"
+inflection@1.12.0:
+  version "1.12.0"
+  resolved "https://registry.yarnpkg.com/inflection/-/inflection-1.12.0.tgz#a200935656d6f5f6bc4dc7502e1aecb703228416"
 
 inflight@^1.0.4:
   version "1.0.6"
@@ -3344,10 +3768,6 @@ interpret@^1.0.0:
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.0.3.tgz#cbc35c62eeee73f19ab7b10a801511401afc0f90"
 
-intersect-arrays-to-stream@^0.0.3:
-  version "0.0.3"
-  resolved "https://registry.yarnpkg.com/intersect-arrays-to-stream/-/intersect-arrays-to-stream-0.0.3.tgz#fc0318953e872f12a12f3d33d04f4e7630e59f3b"
-
 invariant@^2.2.0, invariant@^2.2.2:
   version "2.2.2"
   resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360"
@@ -3358,6 +3778,34 @@ invert-kv@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6"
 
+ioredis@3.1.4, ioredis@^3.1.4:
+  version "3.1.4"
+  resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-3.1.4.tgz#8688293f5f2f1757e1c812ad17cce49f46d811bc"
+  dependencies:
+    bluebird "^3.3.4"
+    cluster-key-slot "^1.0.6"
+    debug "^2.2.0"
+    denque "^1.1.0"
+    flexbuffer "0.0.6"
+    lodash.assign "^4.2.0"
+    lodash.bind "^4.2.1"
+    lodash.clone "^4.5.0"
+    lodash.clonedeep "^4.5.0"
+    lodash.defaults "^4.2.0"
+    lodash.difference "^4.5.0"
+    lodash.flatten "^4.4.0"
+    lodash.foreach "^4.5.0"
+    lodash.isempty "^4.4.0"
+    lodash.keys "^4.2.0"
+    lodash.noop "^3.0.1"
+    lodash.partial "^4.2.1"
+    lodash.pick "^4.4.0"
+    lodash.sample "^4.2.1"
+    lodash.shuffle "^4.2.0"
+    lodash.values "^4.3.0"
+    redis-commands "^1.2.0"
+    redis-parser "^2.4.0"
+
 ip-regex@^1.0.1:
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-1.0.3.tgz#dc589076f659f419c222039a33316f1c7387effd"
@@ -3370,9 +3818,9 @@ ipaddr.js@1.3.0:
   version "1.3.0"
   resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.3.0.tgz#1e03a52fdad83a8bbb2b25cbf4998b4cffcd3dec"
 
-ipaddr.js@1.4.0:
-  version "1.4.0"
-  resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.4.0.tgz#296aca878a821816e5b85d0a285a99bcff4582f0"
+ipaddr.js@1.5.2:
+  version "1.5.2"
+  resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.5.2.tgz#d4b505bde9946987ccf0fc58d9010ff9607e3fa0"
 
 is-arrayish@^0.2.1:
   version "0.2.1"
@@ -3384,6 +3832,10 @@ is-binary-path@^1.0.0:
   dependencies:
     binary-extensions "^1.0.0"
 
+is-bluebird@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/is-bluebird/-/is-bluebird-1.0.2.tgz#096439060f4aa411abee19143a84d6a55346d6e2"
+
 is-buffer@^1.1.5:
   version "1.1.5"
   resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.5.tgz#1f3b26ef613b214b88cbca23cc6c01d87961eecc"
@@ -3458,6 +3910,12 @@ is-glob@^2.0.0, is-glob@^2.0.1:
   dependencies:
     is-extglob "^1.0.0"
 
+is-nan@^1.2.1:
+  version "1.2.1"
+  resolved "https://registry.yarnpkg.com/is-nan/-/is-nan-1.2.1.tgz#9faf65b6fb6db24b7f5c0628475ea71f988401e2"
+  dependencies:
+    define-properties "^1.1.1"
+
 is-npm@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-1.0.0.tgz#f2fb63a65e4905b406c86072765a1a4dc793b9f4"
@@ -3474,6 +3932,10 @@ is-number@^3.0.0:
   dependencies:
     kind-of "^3.0.2"
 
+is-obj@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f"
+
 is-object@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.1.tgz#8952688c5ec2ffd6b03ecc85e769e02903083470"
@@ -3554,14 +4016,6 @@ isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
 
-isarray@2.0.1:
-  version "2.0.1"
-  resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.1.tgz#a37d94ed9cda2d59865c9f76fe596ee1f338741e"
-
-isemail@1.x.x:
-  version "1.2.0"
-  resolved "https://registry.yarnpkg.com/isemail/-/isemail-1.2.0.tgz#be03df8cc3e29de4d2c5df6501263f1fa4595e9a"
-
 isexe@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
@@ -3646,226 +4100,246 @@ isurl@^1.0.0-alpha5:
     has-to-string-tag-x "^1.2.0"
     is-object "^1.0.1"
 
-jest-changed-files@^20.0.3:
-  version "20.0.3"
-  resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-20.0.3.tgz#9394d5cc65c438406149bef1bf4d52b68e03e3f8"
+iterall@1.1.3:
+  version "1.1.3"
+  resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.1.3.tgz#1cbbff96204056dde6656e2ed2e2226d0e6d72c9"
 
-jest-cli@^20.0.4:
-  version "20.0.4"
-  resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-20.0.4.tgz#e532b19d88ae5bc6c417e8b0593a6fe954b1dc93"
+iterall@^1.1.0:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.1.1.tgz#f7f0af11e9a04ec6426260f5019d9fcca4d50214"
+
+jackpot@>=0.0.6:
+  version "0.0.6"
+  resolved "https://registry.yarnpkg.com/jackpot/-/jackpot-0.0.6.tgz#3cff064285cbf66f4eab2593c90bce816a821849"
   dependencies:
-    ansi-escapes "^1.4.0"
-    callsites "^2.0.0"
-    chalk "^1.1.3"
+    retry "0.6.0"
+
+jest-changed-files@^21.2.0:
+  version "21.2.0"
+  resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-21.2.0.tgz#5dbeecad42f5d88b482334902ce1cba6d9798d29"
+  dependencies:
+    throat "^4.0.0"
+
+jest-cli@^21.2.1:
+  version "21.2.1"
+  resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-21.2.1.tgz#9c528b6629d651911138d228bdb033c157ec8c00"
+  dependencies:
+    ansi-escapes "^3.0.0"
+    chalk "^2.0.1"
+    glob "^7.1.2"
     graceful-fs "^4.1.11"
     is-ci "^1.0.10"
     istanbul-api "^1.1.1"
     istanbul-lib-coverage "^1.0.1"
     istanbul-lib-instrument "^1.4.2"
     istanbul-lib-source-maps "^1.1.0"
-    jest-changed-files "^20.0.3"
-    jest-config "^20.0.4"
-    jest-docblock "^20.0.3"
-    jest-environment-jsdom "^20.0.3"
-    jest-haste-map "^20.0.4"
-    jest-jasmine2 "^20.0.4"
-    jest-message-util "^20.0.3"
-    jest-regex-util "^20.0.3"
-    jest-resolve-dependencies "^20.0.3"
-    jest-runtime "^20.0.4"
-    jest-snapshot "^20.0.3"
-    jest-util "^20.0.3"
+    jest-changed-files "^21.2.0"
+    jest-config "^21.2.1"
+    jest-environment-jsdom "^21.2.1"
+    jest-haste-map "^21.2.0"
+    jest-message-util "^21.2.1"
+    jest-regex-util "^21.2.0"
+    jest-resolve-dependencies "^21.2.0"
+    jest-runner "^21.2.1"
+    jest-runtime "^21.2.1"
+    jest-snapshot "^21.2.1"
+    jest-util "^21.2.1"
     micromatch "^2.3.11"
     node-notifier "^5.0.2"
-    pify "^2.3.0"
+    pify "^3.0.0"
     slash "^1.0.0"
-    string-length "^1.0.1"
-    throat "^3.0.0"
+    string-length "^2.0.0"
+    strip-ansi "^4.0.0"
     which "^1.2.12"
     worker-farm "^1.3.1"
-    yargs "^7.0.2"
+    yargs "^9.0.0"
 
-jest-config@^20.0.4:
-  version "20.0.4"
-  resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-20.0.4.tgz#e37930ab2217c913605eff13e7bd763ec48faeea"
+jest-config@^21.2.1:
+  version "21.2.1"
+  resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-21.2.1.tgz#c7586c79ead0bcc1f38c401e55f964f13bf2a480"
   dependencies:
-    chalk "^1.1.3"
+    chalk "^2.0.1"
     glob "^7.1.1"
-    jest-environment-jsdom "^20.0.3"
-    jest-environment-node "^20.0.3"
-    jest-jasmine2 "^20.0.4"
-    jest-matcher-utils "^20.0.3"
-    jest-regex-util "^20.0.3"
-    jest-resolve "^20.0.4"
-    jest-validate "^20.0.3"
-    pretty-format "^20.0.3"
+    jest-environment-jsdom "^21.2.1"
+    jest-environment-node "^21.2.1"
+    jest-get-type "^21.2.0"
+    jest-jasmine2 "^21.2.1"
+    jest-regex-util "^21.2.0"
+    jest-resolve "^21.2.0"
+    jest-util "^21.2.1"
+    jest-validate "^21.2.1"
+    pretty-format "^21.2.1"
 
-jest-diff@^20.0.3:
-  version "20.0.3"
-  resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-20.0.3.tgz#81f288fd9e675f0fb23c75f1c2b19445fe586617"
+jest-diff@^21.2.1:
+  version "21.2.1"
+  resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-21.2.1.tgz#46cccb6cab2d02ce98bc314011764bb95b065b4f"
   dependencies:
-    chalk "^1.1.3"
+    chalk "^2.0.1"
     diff "^3.2.0"
-    jest-matcher-utils "^20.0.3"
-    pretty-format "^20.0.3"
+    jest-get-type "^21.2.0"
+    pretty-format "^21.2.1"
 
-jest-docblock@^20.0.3:
-  version "20.0.3"
-  resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-20.0.3.tgz#17bea984342cc33d83c50fbe1545ea0efaa44712"
+jest-docblock@^21.2.0:
+  version "21.2.0"
+  resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-21.2.0.tgz#51529c3b30d5fd159da60c27ceedc195faf8d414"
 
-jest-environment-jsdom@^20.0.3:
-  version "20.0.3"
-  resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-20.0.3.tgz#048a8ac12ee225f7190417713834bb999787de99"
+jest-environment-jsdom@^21.2.1:
+  version "21.2.1"
+  resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-21.2.1.tgz#38d9980c8259b2a608ec232deee6289a60d9d5b4"
   dependencies:
-    jest-mock "^20.0.3"
-    jest-util "^20.0.3"
+    jest-mock "^21.2.0"
+    jest-util "^21.2.1"
     jsdom "^9.12.0"
 
-jest-environment-node@^20.0.3:
-  version "20.0.3"
-  resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-20.0.3.tgz#d488bc4612af2c246e986e8ae7671a099163d403"
+jest-environment-node@^21.2.1:
+  version "21.2.1"
+  resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-21.2.1.tgz#98c67df5663c7fbe20f6e792ac2272c740d3b8c8"
   dependencies:
-    jest-mock "^20.0.3"
-    jest-util "^20.0.3"
+    jest-mock "^21.2.0"
+    jest-util "^21.2.1"
 
-jest-haste-map@^20.0.4:
-  version "20.0.5"
-  resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-20.0.5.tgz#abad74efb1a005974a7b6517e11010709cab9112"
+jest-get-type@^21.2.0:
+  version "21.2.0"
+  resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-21.2.0.tgz#f6376ab9db4b60d81e39f30749c6c466f40d4a23"
+
+jest-haste-map@^21.2.0:
+  version "21.2.0"
+  resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-21.2.0.tgz#1363f0a8bb4338f24f001806571eff7a4b2ff3d8"
   dependencies:
     fb-watchman "^2.0.0"
     graceful-fs "^4.1.11"
-    jest-docblock "^20.0.3"
+    jest-docblock "^21.2.0"
     micromatch "^2.3.11"
-    sane "~1.6.0"
+    sane "^2.0.0"
     worker-farm "^1.3.1"
 
-jest-jasmine2@^20.0.4:
-  version "20.0.4"
-  resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-20.0.4.tgz#fcc5b1411780d911d042902ef1859e852e60d5e1"
+jest-jasmine2@^21.2.1:
+  version "21.2.1"
+  resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-21.2.1.tgz#9cc6fc108accfa97efebce10c4308548a4ea7592"
   dependencies:
-    chalk "^1.1.3"
+    chalk "^2.0.1"
+    expect "^21.2.1"
     graceful-fs "^4.1.11"
-    jest-diff "^20.0.3"
-    jest-matcher-utils "^20.0.3"
-    jest-matchers "^20.0.3"
-    jest-message-util "^20.0.3"
-    jest-snapshot "^20.0.3"
-    once "^1.4.0"
-    p-map "^1.1.1"
+    jest-diff "^21.2.1"
+    jest-matcher-utils "^21.2.1"
+    jest-message-util "^21.2.1"
+    jest-snapshot "^21.2.1"
+    p-cancelable "^0.3.0"
 
-jest-junit@~3.1.0:
-  version "3.1.0"
-  resolved "https://registry.yarnpkg.com/jest-junit/-/jest-junit-3.1.0.tgz#3bd0b7a8bfd5b91f86376d44ff0f4c7f136f4287"
+jest-matcher-utils@^21.2.1:
+  version "21.2.1"
+  resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-21.2.1.tgz#72c826eaba41a093ac2b4565f865eb8475de0f64"
   dependencies:
-    mkdirp "^0.5.1"
-    strip-ansi "^4.0.0"
-    xml "^1.0.1"
+    chalk "^2.0.1"
+    jest-get-type "^21.2.0"
+    pretty-format "^21.2.1"
 
-jest-matcher-utils@^20.0.3:
-  version "20.0.3"
-  resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-20.0.3.tgz#b3a6b8e37ca577803b0832a98b164f44b7815612"
+jest-message-util@^21.2.1:
+  version "21.2.1"
+  resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-21.2.1.tgz#bfe5d4692c84c827d1dcf41823795558f0a1acbe"
   dependencies:
-    chalk "^1.1.3"
-    pretty-format "^20.0.3"
-
-jest-matchers@^20.0.3:
-  version "20.0.3"
-  resolved "https://registry.yarnpkg.com/jest-matchers/-/jest-matchers-20.0.3.tgz#ca69db1c32db5a6f707fa5e0401abb55700dfd60"
-  dependencies:
-    jest-diff "^20.0.3"
-    jest-matcher-utils "^20.0.3"
-    jest-message-util "^20.0.3"
-    jest-regex-util "^20.0.3"
-
-jest-message-util@^20.0.3:
-  version "20.0.3"
-  resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-20.0.3.tgz#6aec2844306fcb0e6e74d5796c1006d96fdd831c"
-  dependencies:
-    chalk "^1.1.3"
+    chalk "^2.0.1"
     micromatch "^2.3.11"
     slash "^1.0.0"
 
-jest-mock@^20.0.3:
-  version "20.0.3"
-  resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-20.0.3.tgz#8bc070e90414aa155c11a8d64c869a0d5c71da59"
+jest-mock@^21.2.0:
+  version "21.2.0"
+  resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-21.2.0.tgz#7eb0770e7317968165f61ea2a7281131534b3c0f"
 
-jest-regex-util@^20.0.3:
-  version "20.0.3"
-  resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-20.0.3.tgz#85bbab5d133e44625b19faf8c6aa5122d085d762"
+jest-regex-util@^21.2.0:
+  version "21.2.0"
+  resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-21.2.0.tgz#1b1e33e63143babc3e0f2e6c9b5ba1eb34b2d530"
 
-jest-resolve-dependencies@^20.0.3:
-  version "20.0.3"
-  resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-20.0.3.tgz#6e14a7b717af0f2cb3667c549de40af017b1723a"
+jest-resolve-dependencies@^21.2.0:
+  version "21.2.0"
+  resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-21.2.0.tgz#9e231e371e1a736a1ad4e4b9a843bc72bfe03d09"
   dependencies:
-    jest-regex-util "^20.0.3"
+    jest-regex-util "^21.2.0"
 
-jest-resolve@^20.0.4:
-  version "20.0.4"
-  resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-20.0.4.tgz#9448b3e8b6bafc15479444c6499045b7ffe597a5"
+jest-resolve@^21.2.0:
+  version "21.2.0"
+  resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-21.2.0.tgz#068913ad2ba6a20218e5fd32471f3874005de3a6"
   dependencies:
     browser-resolve "^1.11.2"
+    chalk "^2.0.1"
     is-builtin-module "^1.0.0"
-    resolve "^1.3.2"
 
-jest-runtime@^20.0.4:
-  version "20.0.4"
-  resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-20.0.4.tgz#a2c802219c4203f754df1404e490186169d124d8"
+jest-runner@^21.2.1:
+  version "21.2.1"
+  resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-21.2.1.tgz#194732e3e518bfb3d7cbfc0fd5871246c7e1a467"
+  dependencies:
+    jest-config "^21.2.1"
+    jest-docblock "^21.2.0"
+    jest-haste-map "^21.2.0"
+    jest-jasmine2 "^21.2.1"
+    jest-message-util "^21.2.1"
+    jest-runtime "^21.2.1"
+    jest-util "^21.2.1"
+    pify "^3.0.0"
+    throat "^4.0.0"
+    worker-farm "^1.3.1"
+
+jest-runtime@^21.2.1:
+  version "21.2.1"
+  resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-21.2.1.tgz#99dce15309c670442eee2ebe1ff53a3cbdbbb73e"
   dependencies:
     babel-core "^6.0.0"
-    babel-jest "^20.0.3"
+    babel-jest "^21.2.0"
     babel-plugin-istanbul "^4.0.0"
-    chalk "^1.1.3"
+    chalk "^2.0.1"
     convert-source-map "^1.4.0"
     graceful-fs "^4.1.11"
-    jest-config "^20.0.4"
-    jest-haste-map "^20.0.4"
-    jest-regex-util "^20.0.3"
-    jest-resolve "^20.0.4"
-    jest-util "^20.0.3"
+    jest-config "^21.2.1"
+    jest-haste-map "^21.2.0"
+    jest-regex-util "^21.2.0"
+    jest-resolve "^21.2.0"
+    jest-util "^21.2.1"
     json-stable-stringify "^1.0.1"
     micromatch "^2.3.11"
+    slash "^1.0.0"
     strip-bom "3.0.0"
-    yargs "^7.0.2"
+    write-file-atomic "^2.1.0"
+    yargs "^9.0.0"
 
-jest-snapshot@^20.0.3:
-  version "20.0.3"
-  resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-20.0.3.tgz#5b847e1adb1a4d90852a7f9f125086e187c76566"
+jest-snapshot@^21.2.1:
+  version "21.2.1"
+  resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-21.2.1.tgz#29e49f16202416e47343e757e5eff948c07fd7b0"
   dependencies:
-    chalk "^1.1.3"
-    jest-diff "^20.0.3"
-    jest-matcher-utils "^20.0.3"
-    jest-util "^20.0.3"
+    chalk "^2.0.1"
+    jest-diff "^21.2.1"
+    jest-matcher-utils "^21.2.1"
+    mkdirp "^0.5.1"
     natural-compare "^1.4.0"
-    pretty-format "^20.0.3"
+    pretty-format "^21.2.1"
 
-jest-util@^20.0.3:
-  version "20.0.3"
-  resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-20.0.3.tgz#0c07f7d80d82f4e5a67c6f8b9c3fe7f65cfd32ad"
+jest-util@^21.2.1:
+  version "21.2.1"
+  resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-21.2.1.tgz#a274b2f726b0897494d694a6c3d6a61ab819bb78"
   dependencies:
-    chalk "^1.1.3"
+    callsites "^2.0.0"
+    chalk "^2.0.1"
     graceful-fs "^4.1.11"
-    jest-message-util "^20.0.3"
-    jest-mock "^20.0.3"
-    jest-validate "^20.0.3"
-    leven "^2.1.0"
+    jest-message-util "^21.2.1"
+    jest-mock "^21.2.0"
+    jest-validate "^21.2.1"
     mkdirp "^0.5.1"
 
-jest-validate@^20.0.3:
-  version "20.0.3"
-  resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-20.0.3.tgz#d0cfd1de4f579f298484925c280f8f1d94ec3cab"
+jest-validate@^21.2.1:
+  version "21.2.1"
+  resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-21.2.1.tgz#cc0cbca653cd54937ba4f2a111796774530dd3c7"
   dependencies:
-    chalk "^1.1.3"
-    jest-matcher-utils "^20.0.3"
+    chalk "^2.0.1"
+    jest-get-type "^21.2.0"
     leven "^2.1.0"
-    pretty-format "^20.0.3"
+    pretty-format "^21.2.1"
 
-jest@~20.0.4:
-  version "20.0.4"
-  resolved "https://registry.yarnpkg.com/jest/-/jest-20.0.4.tgz#3dd260c2989d6dad678b1e9cc4d91944f6d602ac"
+jest@21.2.1:
+  version "21.2.1"
+  resolved "https://registry.yarnpkg.com/jest/-/jest-21.2.1.tgz#c964e0b47383768a1438e3ccf3c3d470327604e1"
   dependencies:
-    jest-cli "^20.0.4"
+    jest-cli "^21.2.1"
 
-jimp@~0.2.28:
+jimp@0.2.28:
   version "0.2.28"
   resolved "https://registry.yarnpkg.com/jimp/-/jimp-0.2.28.tgz#dd529a937190f42957a7937d1acc3a7762996ea2"
   dependencies:
@@ -3886,42 +4360,21 @@ jimp@~0.2.28:
     tinycolor2 "^1.1.2"
     url-regex "^3.0.0"
 
-joi@^6.10.1:
-  version "6.10.1"
-  resolved "https://registry.yarnpkg.com/joi/-/joi-6.10.1.tgz#4d50c318079122000fe5f16af1ff8e1917b77e06"
-  dependencies:
-    hoek "2.x.x"
-    isemail "1.x.x"
-    moment "2.x.x"
-    topo "1.x.x"
-
 jpeg-js@^0.2.0:
   version "0.2.0"
   resolved "https://registry.yarnpkg.com/jpeg-js/-/jpeg-js-0.2.0.tgz#53e448ec9d263e683266467e9442d2c5a2ef5482"
 
-jquery-contextmenu@~2.5.0:
-  version "2.5.0"
-  resolved "https://registry.yarnpkg.com/jquery-contextmenu/-/jquery-contextmenu-2.5.0.tgz#940dbadbd0f2d7e0a0a8f1bbc5e71667d8257405"
+jquery-contextmenu@2.6.2:
+  version "2.6.2"
+  resolved "https://registry.yarnpkg.com/jquery-contextmenu/-/jquery-contextmenu-2.6.2.tgz#83c7ba45c67c814cc4095b19551fd12e5d71da7e"
 
-jquery-simple-upload@~1.0.0:
+jquery-simple-upload@1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/jquery-simple-upload/-/jquery-simple-upload-1.0.0.tgz#0b89238bf9b35b77b41bfe11840c1b383e97a3bd"
   dependencies:
     jquery ">=1.7.0"
 
-jquery-smooth-scroll@~2.2.0:
-  version "2.2.0"
-  resolved "https://registry.yarnpkg.com/jquery-smooth-scroll/-/jquery-smooth-scroll-2.2.0.tgz#87dc1add84168b7f466b3cdaeeb81c803fd22a2a"
-  dependencies:
-    jquery ">=1.7.0"
-
-jquery-sticky@~1.0.4:
-  version "1.0.4"
-  resolved "https://registry.yarnpkg.com/jquery-sticky/-/jquery-sticky-1.0.4.tgz#2fe8d03dc904685340daa12cbdd1ca0c921b09ac"
-  dependencies:
-    jquery "*"
-
-jquery@*, jquery@>=1.7.0, jquery@~3.2.1:
+jquery@3.2.1, jquery@>=1.7.0:
   version "3.2.1"
   resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.2.1.tgz#5c4d9de652af6cd0a770154a631bba12b015c787"
 
@@ -3929,6 +4382,14 @@ js-base64@^2.1.8:
   version "2.1.9"
   resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.1.9.tgz#f0e80ae039a4bd654b5f281fc93f04a914a7fcce"
 
+js-cookie@2.1.4:
+  version "2.1.4"
+  resolved "https://registry.yarnpkg.com/js-cookie/-/js-cookie-2.1.4.tgz#da4ec503866f149d164cf25f579ef31015025d8d"
+
+js-string-escape@1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/js-string-escape/-/js-string-escape-1.0.1.tgz#e2625badbc0d67c7533e9edc1068c587ae4137ef"
+
 js-stringify@^1.0.1:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/js-stringify/-/js-stringify-1.0.2.tgz#1736fddfd9724f28a3682adc6230ae7e4e9679db"
@@ -3937,6 +4398,13 @@ js-tokens@^3.0.0, js-tokens@^3.0.2:
   version "3.0.2"
   resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b"
 
+js-yaml@3.10.0:
+  version "3.10.0"
+  resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.10.0.tgz#2e78441646bd4682e963f22b6e92823c309c62dc"
+  dependencies:
+    argparse "^1.0.7"
+    esprima "^4.0.0"
+
 js-yaml@3.5.4:
   version "3.5.4"
   resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.5.4.tgz#f64f16dcd78beb9ce8361068e733ebe47b079179"
@@ -3951,7 +4419,7 @@ js-yaml@^3.7.0:
     argparse "^1.0.7"
     esprima "^4.0.0"
 
-js-yaml@^3.9.1, js-yaml@~3.9.1:
+js-yaml@^3.9.1:
   version "3.9.1"
   resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.9.1.tgz#08775cebdfdd359209f0d2acd383c8f86a6904a0"
   dependencies:
@@ -4030,9 +4498,9 @@ jsonfile@^2.1.0:
   optionalDependencies:
     graceful-fs "^4.1.6"
 
-jsonfile@^3.0.0:
-  version "3.0.1"
-  resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-3.0.1.tgz#a5ecc6f65f53f662c4415c7675a0331d0992ec66"
+jsonfile@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb"
   optionalDependencies:
     graceful-fs "^4.1.6"
 
@@ -4040,16 +4508,17 @@ jsonify@~0.0.0:
   version "0.0.0"
   resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73"
 
-jsonparse@^1.2.0:
-  version "1.3.1"
-  resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280"
-
-jsonwebtoken@~7.4.3:
-  version "7.4.3"
-  resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-7.4.3.tgz#77f5021de058b605a1783fa1283e99812e645638"
+jsonwebtoken@8.0.1:
+  version "8.0.1"
+  resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-8.0.1.tgz#50daef8d0a8c7de2cd06bc1013b75b04ccf3f0cf"
   dependencies:
-    joi "^6.10.1"
     jws "^3.1.4"
+    lodash.includes "^4.3.0"
+    lodash.isboolean "^3.0.3"
+    lodash.isinteger "^4.0.4"
+    lodash.isnumber "^3.0.3"
+    lodash.isplainobject "^4.0.6"
+    lodash.isstring "^4.0.1"
     lodash.once "^4.0.0"
     ms "^2.0.0"
     xtend "^4.0.1"
@@ -4087,17 +4556,9 @@ jws@^3.1.4:
     jwa "^1.1.4"
     safe-buffer "^5.0.1"
 
-kareem@1.4.2:
-  version "1.4.2"
-  resolved "https://registry.yarnpkg.com/kareem/-/kareem-1.4.2.tgz#3b4af5dbfaf3ac1c08b8e5518fdd81ba90c2ab72"
-
-kareem@1.5.0:
-  version "1.5.0"
-  resolved "https://registry.yarnpkg.com/kareem/-/kareem-1.5.0.tgz#e3e4101d9dcfde299769daf4b4db64d895d17448"
-
-keygrip@~1.0.0:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/keygrip/-/keygrip-1.0.1.tgz#b02fa4816eef21a8c4b35ca9e52921ffc89a30e9"
+keygrip@~1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/keygrip/-/keygrip-1.0.2.tgz#ad3297c557069dea8bcfe7a4fa491b75c5ddeb91"
 
 kind-of@^3.0.2:
   version "3.2.2"
@@ -4111,17 +4572,17 @@ kind-of@^4.0.0:
   dependencies:
     is-buffer "^1.1.5"
 
-klaw@~2.1.0:
+klaw@2.1.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/klaw/-/klaw-2.1.0.tgz#694a269019f4321d9233fb1b9abdae21e38259fb"
   dependencies:
     graceful-fs "^4.1.9"
 
-latest-version@^1.0.0:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-1.0.1.tgz#72cfc46e3e8d1be651e1ebb54ea9f6ea96f374bb"
+latest-version@^3.0.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-3.1.0.tgz#a205383fea322b33b5ae3b18abee0dc2f356ee15"
   dependencies:
-    package-json "^1.0.0"
+    package-json "^4.0.0"
 
 lazy-cache@^1.0.3:
   version "1.0.4"
@@ -4175,63 +4636,6 @@ lego-api@^1.0.7:
   dependencies:
     chain-able "^3.0.0"
 
-level-codec@~6.1.0:
-  version "6.1.0"
-  resolved "https://registry.yarnpkg.com/level-codec/-/level-codec-6.1.0.tgz#f5df0a99582f76dac43855151ab6f4e4d0d60045"
-
-level-codec@~7.0.0:
-  version "7.0.1"
-  resolved "https://registry.yarnpkg.com/level-codec/-/level-codec-7.0.1.tgz#341f22f907ce0f16763f24bddd681e395a0fb8a7"
-
-level-errors@^1.0.3, level-errors@~1.0.3:
-  version "1.0.4"
-  resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-1.0.4.tgz#3585e623974c737a93755492a43c0267cda4425f"
-  dependencies:
-    errno "~0.1.1"
-
-level-iterator-stream@~1.3.0:
-  version "1.3.1"
-  resolved "https://registry.yarnpkg.com/level-iterator-stream/-/level-iterator-stream-1.3.1.tgz#e43b78b1a8143e6fa97a4f485eb8ea530352f2ed"
-  dependencies:
-    inherits "^2.0.1"
-    level-errors "^1.0.3"
-    readable-stream "^1.0.33"
-    xtend "^4.0.0"
-
-leveldown@^1.6.0, leveldown@^1.7.1:
-  version "1.7.2"
-  resolved "https://registry.yarnpkg.com/leveldown/-/leveldown-1.7.2.tgz#5e3467bb27ee246a4a7b8dbd8fb2b16206a6eb8b"
-  dependencies:
-    abstract-leveldown "~2.6.1"
-    bindings "~1.2.1"
-    fast-future "~1.0.2"
-    nan "~2.6.1"
-    prebuild-install "^2.1.0"
-
-levelup@^1.3.8:
-  version "1.3.8"
-  resolved "https://registry.yarnpkg.com/levelup/-/levelup-1.3.8.tgz#fb442c488efbea1043f7eb9929a792a74fbd1da6"
-  dependencies:
-    deferred-leveldown "~1.2.1"
-    level-codec "~6.1.0"
-    level-errors "~1.0.3"
-    level-iterator-stream "~1.3.0"
-    prr "~1.0.1"
-    semver "~5.1.0"
-    xtend "~4.0.0"
-
-levelup@~1.3.9:
-  version "1.3.9"
-  resolved "https://registry.yarnpkg.com/levelup/-/levelup-1.3.9.tgz#2dbcae845b2bb2b6bea84df334c475533bbd82ab"
-  dependencies:
-    deferred-leveldown "~1.2.1"
-    level-codec "~7.0.0"
-    level-errors "~1.0.3"
-    level-iterator-stream "~1.3.0"
-    prr "~1.0.1"
-    semver "~5.4.1"
-    xtend "~4.0.0"
-
 leven@^2.1.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/leven/-/leven-2.1.0.tgz#c2e7a9f772094dee9d34202ae8acce4687875580"
@@ -4287,17 +4691,7 @@ locate-path@^2.0.0:
     p-locate "^2.0.0"
     path-exists "^3.0.0"
 
-lodash-cli@~4.17.4:
-  version "4.17.4"
-  resolved "https://registry.yarnpkg.com/lodash-cli/-/lodash-cli-4.17.4.tgz#23b727cd0e91e28484fafda1521900a8a811df81"
-  dependencies:
-    closure-compiler "0.2.12"
-    glob "7.1.1"
-    lodash "4.17.4"
-    semver "5.3.0"
-    uglify-js "2.7.5"
-
-lodash-es@~4.17.4:
+lodash-es@^4.2.1:
   version "4.17.4"
   resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.4.tgz#dcc1d7552e150a0640073ba9cb31d70f032950e7"
 
@@ -4344,7 +4738,15 @@ lodash.assign@^4.2.0:
   version "4.2.0"
   resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7"
 
-lodash.clonedeep@^4.3.2:
+lodash.bind@^4.2.1:
+  version "4.2.1"
+  resolved "https://registry.yarnpkg.com/lodash.bind/-/lodash.bind-4.2.1.tgz#7ae3017e939622ac31b7d7d7dcb1b34db1690d35"
+
+lodash.clone@^4.5.0:
+  version "4.5.0"
+  resolved "https://registry.yarnpkg.com/lodash.clone/-/lodash.clone-4.5.0.tgz#195870450f5a13192478df4bc3d23d2dea1907b6"
+
+lodash.clonedeep@^4.3.2, lodash.clonedeep@^4.5.0:
   version "4.5.0"
   resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef"
 
@@ -4359,6 +4761,10 @@ lodash.defaults@^3.1.2:
     lodash.assign "^3.0.0"
     lodash.restparam "^3.0.0"
 
+lodash.defaults@^4.2.0:
+  version "4.2.0"
+  resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c"
+
 lodash.difference@^4.5.0:
   version "4.5.0"
   resolved "https://registry.yarnpkg.com/lodash.difference/-/lodash.difference-4.5.0.tgz#9ccb4e505d486b91651345772885a2df27fd017c"
@@ -4367,9 +4773,17 @@ lodash.findindex@^4.4.0:
   version "4.6.0"
   resolved "https://registry.yarnpkg.com/lodash.findindex/-/lodash.findindex-4.6.0.tgz#a3245dee61fb9b6e0624b535125624bb69c11106"
 
-lodash.intersection@^4.4.0:
+lodash.flatten@^4.4.0:
   version "4.4.0"
-  resolved "https://registry.yarnpkg.com/lodash.intersection/-/lodash.intersection-4.4.0.tgz#0a11ba631d0e95c23c7f2f4cbb9a692ed178e705"
+  resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f"
+
+lodash.foreach@^4.5.0:
+  version "4.5.0"
+  resolved "https://registry.yarnpkg.com/lodash.foreach/-/lodash.foreach-4.5.0.tgz#1a6a35eace401280c7f06dddec35165ab27e3e53"
+
+lodash.includes@^4.3.0:
+  version "4.3.0"
+  resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f"
 
 lodash.isarguments@^3.0.0:
   version "3.1.0"
@@ -4379,10 +4793,34 @@ lodash.isarray@^3.0.0:
   version "3.0.4"
   resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55"
 
-lodash.isequal@^4.0.0, lodash.isequal@^4.1.3:
+lodash.isboolean@^3.0.3:
+  version "3.0.3"
+  resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6"
+
+lodash.isempty@^4.4.0:
+  version "4.4.0"
+  resolved "https://registry.yarnpkg.com/lodash.isempty/-/lodash.isempty-4.4.0.tgz#6f86cbedd8be4ec987be9aaf33c9684db1b31e7e"
+
+lodash.isequal@^4.0.0:
   version "4.5.0"
   resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
 
+lodash.isinteger@^4.0.4:
+  version "4.0.4"
+  resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343"
+
+lodash.isnumber@^3.0.3:
+  version "3.0.3"
+  resolved "https://registry.yarnpkg.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz#3ce76810c5928d03352301ac287317f11c0b1ffc"
+
+lodash.isplainobject@^4.0.6:
+  version "4.0.6"
+  resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb"
+
+lodash.isstring@^4.0.1:
+  version "4.0.1"
+  resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451"
+
 lodash.keys@^3.0.0:
   version "3.1.2"
   resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a"
@@ -4391,6 +4829,10 @@ lodash.keys@^3.0.0:
     lodash.isarguments "^3.0.0"
     lodash.isarray "^3.0.0"
 
+lodash.keys@^4.2.0:
+  version "4.2.0"
+  resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-4.2.0.tgz#a08602ac12e4fb83f91fc1fb7a360a4d9ba35205"
+
 lodash.merge@^4.6.0:
   version "4.6.0"
   resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.0.tgz#69884ba144ac33fe699737a6086deffadd0f89c5"
@@ -4399,6 +4841,10 @@ lodash.mergewith@^4.6.0:
   version "4.6.0"
   resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.0.tgz#150cf0a16791f5903b8891eab154609274bdea55"
 
+lodash.noop@^3.0.1:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/lodash.noop/-/lodash.noop-3.0.1.tgz#38188f4d650a3a474258439b96ec45b32617133c"
+
 lodash.once@^4.0.0:
   version "4.1.1"
   resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac"
@@ -4407,6 +4853,14 @@ lodash.padend@^4.6.1:
   version "4.6.1"
   resolved "https://registry.yarnpkg.com/lodash.padend/-/lodash.padend-4.6.1.tgz#53ccba047d06e158d311f45da625f4e49e6f166e"
 
+lodash.partial@^4.2.1:
+  version "4.2.1"
+  resolved "https://registry.yarnpkg.com/lodash.partial/-/lodash.partial-4.2.1.tgz#49f3d8cfdaa3bff8b3a91d127e923245418961d4"
+
+lodash.pick@^4.4.0:
+  version "4.4.0"
+  resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3"
+
 lodash.repeat@^4.0.0:
   version "4.1.0"
   resolved "https://registry.yarnpkg.com/lodash.repeat/-/lodash.repeat-4.1.0.tgz#fc7de8131d8c8ac07e4b49f74ffe829d1f2bec44"
@@ -4415,23 +4869,19 @@ lodash.restparam@^3.0.0:
   version "3.6.1"
   resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805"
 
-lodash.sortedindexof@^4.1.0:
-  version "4.1.0"
-  resolved "https://registry.yarnpkg.com/lodash.sortedindexof/-/lodash.sortedindexof-4.1.0.tgz#7b661d2f86f55668770802d56baa8f02d6620f3c"
-
-lodash.spread@^4.2.1:
+lodash.sample@^4.2.1:
   version "4.2.1"
-  resolved "https://registry.yarnpkg.com/lodash.spread/-/lodash.spread-4.2.1.tgz#07bf5569e83b40534f7361d954a9fab02da5d4fc"
+  resolved "https://registry.yarnpkg.com/lodash.sample/-/lodash.sample-4.2.1.tgz#5e4291b0c753fa1abeb0aab8fb29df1b66f07f6d"
 
-lodash.union@^4.6.0:
-  version "4.6.0"
-  resolved "https://registry.yarnpkg.com/lodash.union/-/lodash.union-4.6.0.tgz#48bb5088409f16f1821666641c44dd1aaae3cd88"
+lodash.shuffle@^4.2.0:
+  version "4.2.0"
+  resolved "https://registry.yarnpkg.com/lodash.shuffle/-/lodash.shuffle-4.2.0.tgz#145b5053cf875f6f5c2a33f48b6e9948c6ec7b4b"
 
-lodash.uniq@^4.5.0:
-  version "4.5.0"
-  resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
+lodash.values@^4.3.0:
+  version "4.3.0"
+  resolved "https://registry.yarnpkg.com/lodash.values/-/lodash.values-4.3.0.tgz#a3a6c2b0ebecc5c2cba1c17e6e620fe81b53d347"
 
-lodash@4.17.4, lodash@^4.0.0, lodash@^4.1.0, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.3.0, lodash@~4.17.4:
+lodash@4.17.4, lodash@^4.0.0, lodash@^4.1.0, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.17.1, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0, lodash@~4.17.4:
   version "4.17.4"
   resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"
 
@@ -4449,7 +4899,7 @@ longest@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097"
 
-loose-envify@^1.0.0:
+loose-envify@^1.0.0, loose-envify@^1.1.0:
   version "1.3.1"
   resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848"
   dependencies:
@@ -4477,9 +4927,11 @@ lru-cache@^4.0.0, lru-cache@^4.0.1, lru-cache@^4.0.2:
     pseudomap "^1.0.2"
     yallist "^2.1.2"
 
-ltgt@~2.1.3:
-  version "2.1.3"
-  resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.1.3.tgz#10851a06d9964b971178441c23c9e52698eece34"
+make-dir@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.0.0.tgz#97a011751e91dd87cfadef58832ebb04936de978"
+  dependencies:
+    pify "^2.3.0"
 
 makeerror@1.0.x:
   version "1.0.11"
@@ -4487,6 +4939,10 @@ makeerror@1.0.x:
   dependencies:
     tmpl "1.0.x"
 
+manakin@~0.5.1:
+  version "0.5.1"
+  resolved "https://registry.yarnpkg.com/manakin/-/manakin-0.5.1.tgz#c4a7116f6b00df3d5f1a37ad3ca515d22065a658"
+
 map-obj@^1.0.0, map-obj@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d"
@@ -4495,25 +4951,25 @@ map-stream@~0.1.0:
   version "0.1.0"
   resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.1.0.tgz#e56aa94c4c8055a16404a0674b78f215f7c8e194"
 
-markdown-it-abbr@~1.0.4:
+markdown-it-abbr@1.0.4:
   version "1.0.4"
   resolved "https://registry.yarnpkg.com/markdown-it-abbr/-/markdown-it-abbr-1.0.4.tgz#d66b5364521cbb3dd8aa59dadfba2fb6865c8fd8"
 
-markdown-it-anchor@~4.0.0:
+markdown-it-anchor@4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/markdown-it-anchor/-/markdown-it-anchor-4.0.0.tgz#e87fb5543e01965adf71506c6bf7b0491841b7e3"
   dependencies:
     string "^3.3.3"
 
-markdown-it-attrs@~1.1.0:
-  version "1.1.0"
-  resolved "https://registry.yarnpkg.com/markdown-it-attrs/-/markdown-it-attrs-1.1.0.tgz#6f5c7bc8d0c29e628ef335bcc1e0bf454d204f5d"
+markdown-it-attrs@1.2.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/markdown-it-attrs/-/markdown-it-attrs-1.2.0.tgz#6baad67036a411483d5902c127d46ee229435484"
 
-markdown-it-emoji@~1.4.0:
+markdown-it-emoji@1.4.0:
   version "1.4.0"
   resolved "https://registry.yarnpkg.com/markdown-it-emoji/-/markdown-it-emoji-1.4.0.tgz#9bee0e9a990a963ba96df6980c4fddb05dfb4dcc"
 
-markdown-it-expand-tabs@~1.0.12:
+markdown-it-expand-tabs@1.0.12:
   version "1.0.12"
   resolved "https://registry.yarnpkg.com/markdown-it-expand-tabs/-/markdown-it-expand-tabs-1.0.12.tgz#f54bd2f303f858ee6798ca2bd83fe70144814ca0"
   dependencies:
@@ -4523,19 +4979,19 @@ markdown-it-external-links@0.0.6:
   version "0.0.6"
   resolved "https://registry.yarnpkg.com/markdown-it-external-links/-/markdown-it-external-links-0.0.6.tgz#9503258fce4c81010ea15fe71769d63a1346d801"
 
-markdown-it-footnote@~3.0.1:
+markdown-it-footnote@3.0.1:
   version "3.0.1"
   resolved "https://registry.yarnpkg.com/markdown-it-footnote/-/markdown-it-footnote-3.0.1.tgz#7f3730747cacc86e2fe0bf8a17a710f34791517a"
 
-markdown-it-mathjax@~2.0.0:
+markdown-it-mathjax@2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/markdown-it-mathjax/-/markdown-it-mathjax-2.0.0.tgz#ae2b4f4c5c719a03f9e475c664f7b2685231d9e9"
 
-markdown-it-task-lists@~2.0.1:
+markdown-it-task-lists@2.0.1:
   version "2.0.1"
   resolved "https://registry.yarnpkg.com/markdown-it-task-lists/-/markdown-it-task-lists-2.0.1.tgz#a9ce7f55cde9f45e0fca629071d11d3fd5a69416"
 
-markdown-it@~8.4.0:
+markdown-it@8.4.0:
   version "8.4.0"
   resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-8.4.0.tgz#e2400881bf171f7018ed1bd9da441dac8af6306d"
   dependencies:
@@ -4549,9 +5005,9 @@ marked@*:
   version "0.3.6"
   resolved "https://registry.yarnpkg.com/marked/-/marked-0.3.6.tgz#b2c6c618fccece4ef86c4fc6cb8a7cbf5aeda8d7"
 
-mathjax-node@~1.2.0:
-  version "1.2.0"
-  resolved "https://registry.yarnpkg.com/mathjax-node/-/mathjax-node-1.2.0.tgz#538d01f85ca18b90f3cc6ce68c7caeed44bb9f7f"
+mathjax-node@1.2.1:
+  version "1.2.1"
+  resolved "https://registry.yarnpkg.com/mathjax-node/-/mathjax-node-1.2.1.tgz#f4a0e272149104f2e00a3d268c81e42bee1324fd"
   dependencies:
     jsdom "7.0 - 9.12"
     mathjax "*"
@@ -4574,15 +5030,12 @@ mem@^1.1.0:
   dependencies:
     mimic-fn "^1.0.0"
 
-memdown@~1.2.4:
-  version "1.2.4"
-  resolved "https://registry.yarnpkg.com/memdown/-/memdown-1.2.4.tgz#cd9a34aaf074d53445a271108eb4b8dd4ec0f27f"
+memcached@~0.2.4:
+  version "0.2.8"
+  resolved "https://registry.yarnpkg.com/memcached/-/memcached-0.2.8.tgz#ffbf9498cbc30779625b77e77770bd50dc525212"
   dependencies:
-    abstract-leveldown "2.4.1"
-    functional-red-black-tree "^1.0.1"
-    immediate "^3.2.3"
-    inherits "~2.0.1"
-    ltgt "~2.1.3"
+    hashring "0.0.x"
+    jackpot ">=0.0.6"
 
 meow@^3.7.0:
   version "3.7.0"
@@ -4629,14 +5082,24 @@ micromatch@^2.1.5, micromatch@^2.3.11:
     parse-glob "^3.0.4"
     regex-cache "^0.4.2"
 
-"mime-db@>= 1.27.0 < 2", mime-db@~1.29.0:
-  version "1.29.0"
-  resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.29.0.tgz#48d26d235589651704ac5916ca06001914266878"
+"mime-db@>= 1.29.0 < 2", mime-db@~1.30.0:
+  version "1.30.0"
+  resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.30.0.tgz#74c643da2dd9d6a45399963465b26d5ca7d71f01"
 
 mime-db@~1.27.0:
   version "1.27.0"
   resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.27.0.tgz#820f572296bbd20ec25ed55e5b5de869e5436eb1"
 
+mime-db@~1.29.0:
+  version "1.29.0"
+  resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.29.0.tgz#48d26d235589651704ac5916ca06001914266878"
+
+mime-types@2.1.17, mime-types@~2.1.17:
+  version "2.1.17"
+  resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.17.tgz#09d7a393f03e995a79f8af857b70a9e0ab16557a"
+  dependencies:
+    mime-db "~1.30.0"
+
 mime-types@^2.1.12, mime-types@~2.1.11, mime-types@~2.1.15, mime-types@~2.1.6, mime-types@~2.1.7:
   version "2.1.15"
   resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.15.tgz#a4ebf5064094569237b8cf70046776d09fc92aed"
@@ -4653,6 +5116,10 @@ mime@1.3.4:
   version "1.3.4"
   resolved "https://registry.yarnpkg.com/mime/-/mime-1.3.4.tgz#115f9e3b6b3daf2959983cb38f149a2d40eb5d53"
 
+mime@1.4.1:
+  version "1.4.1"
+  resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6"
+
 mime@^1.3.4:
   version "1.3.6"
   resolved "https://registry.yarnpkg.com/mime/-/mime-1.3.6.tgz#591d84d3653a6b0b4a3b9df8de5aa8108e72e5e0"
@@ -4711,125 +5178,25 @@ mkdirp@0.5.1, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.1:
   dependencies:
     minimist "0.0.8"
 
-moment-timezone@^0.5.x, moment-timezone@~0.5.13:
+moment-timezone@0.5.13, moment-timezone@^0.5.0, moment-timezone@^0.5.4, moment-timezone@^0.5.x:
   version "0.5.13"
   resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.13.tgz#99ce5c7d827262eb0f1f702044177f60745d7b90"
   dependencies:
     moment ">= 2.9.0"
 
-moment@2.x.x, "moment@>= 2.9.0", moment@^2.10.6, moment@^2.16.1, moment@^2.18, moment@^2.18.1, moment@~2.18.1:
+moment@2.18.1, "moment@>= 2.9.0", moment@^2.10.6, moment@^2.13.0, moment@^2.16.1, moment@^2.18:
   version "2.18.1"
   resolved "https://registry.yarnpkg.com/moment/-/moment-2.18.1.tgz#c36193dd3ce1c2eed2adb7c802dbbc77a81b1c0f"
 
-mongodb-core@2.1.11:
-  version "2.1.11"
-  resolved "https://registry.yarnpkg.com/mongodb-core/-/mongodb-core-2.1.11.tgz#1c38776ceb174997a99c28860eed9028da9b3e1a"
-  dependencies:
-    bson "~1.0.4"
-    require_optional "~1.0.0"
-
-mongodb-core@2.1.14:
-  version "2.1.14"
-  resolved "https://registry.yarnpkg.com/mongodb-core/-/mongodb-core-2.1.14.tgz#13cba2764226b5be3d18992af0c963ce5ea0f0fd"
-  dependencies:
-    bson "~1.0.4"
-    require_optional "~1.0.0"
-
-mongodb-core@2.1.15:
-  version "2.1.15"
-  resolved "https://registry.yarnpkg.com/mongodb-core/-/mongodb-core-2.1.15.tgz#841f53b87ffff4c7458189c35c8ae827e1169764"
-  dependencies:
-    bson "~1.0.4"
-    require_optional "~1.0.0"
-
-mongodb@2.2.27:
-  version "2.2.27"
-  resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-2.2.27.tgz#34122034db66d983bcf6ab5adb26a24a70fef6e6"
-  dependencies:
-    es6-promise "3.2.1"
-    mongodb-core "2.1.11"
-    readable-stream "2.2.7"
-
-mongodb@2.2.31, mongodb@~2.2.31:
-  version "2.2.31"
-  resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-2.2.31.tgz#1940445c661e19217bb3bf8245d9854aaef548db"
-  dependencies:
-    es6-promise "3.2.1"
-    mongodb-core "2.1.15"
-    readable-stream "2.2.7"
-
-"mongodb@>= 1.2.0 <3.0.0":
-  version "2.2.30"
-  resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-2.2.30.tgz#8ccd801f676c8172040c2f2b47e9602a0d5634ab"
-  dependencies:
-    es6-promise "3.2.1"
-    mongodb-core "2.1.14"
-    readable-stream "2.2.7"
-
-mongoose@*:
-  version "4.11.3"
-  resolved "https://registry.yarnpkg.com/mongoose/-/mongoose-4.11.3.tgz#f93d427b282c2e798b0fe1532fb41a7dde6e98d3"
-  dependencies:
-    async "2.1.4"
-    bson "~1.0.4"
-    hooks-fixed "2.0.0"
-    kareem "1.4.2"
-    mongodb "2.2.27"
-    mpath "0.3.0"
-    mpromise "0.5.5"
-    mquery "2.3.1"
-    ms "2.0.0"
-    muri "1.2.2"
-    regexp-clone "0.0.1"
-    sliced "1.0.1"
-
-mongoose@~4.11.9:
-  version "4.11.9"
-  resolved "https://registry.yarnpkg.com/mongoose/-/mongoose-4.11.9.tgz#58f89a72e75674d9bcdfa4e65ebe1b49b4477637"
-  dependencies:
-    async "2.1.4"
-    bson "~1.0.4"
-    hooks-fixed "2.0.0"
-    kareem "1.5.0"
-    mongodb "2.2.31"
-    mpath "0.3.0"
-    mpromise "0.5.5"
-    mquery "2.3.1"
-    ms "2.0.0"
-    muri "1.2.2"
-    regexp-clone "0.0.1"
-    sliced "1.0.1"
-
-mpath@0.3.0:
-  version "0.3.0"
-  resolved "https://registry.yarnpkg.com/mpath/-/mpath-0.3.0.tgz#7a58f789e9b5fd3c94520634157960f26bd5ef44"
-
-mpromise@0.5.5:
-  version "0.5.5"
-  resolved "https://registry.yarnpkg.com/mpromise/-/mpromise-0.5.5.tgz#f5b24259d763acc2257b0a0c8c6d866fd51732e6"
-
-mquery@2.3.1:
-  version "2.3.1"
-  resolved "https://registry.yarnpkg.com/mquery/-/mquery-2.3.1.tgz#9ab36749714800ff0bb53a681ce4bc4d5f07c87b"
-  dependencies:
-    bluebird "2.10.2"
-    debug "2.6.8"
-    regexp-clone "0.0.1"
-    sliced "0.0.5"
-
 ms@0.7.1:
   version "0.7.1"
   resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098"
 
-ms@0.7.2:
-  version "0.7.2"
-  resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.2.tgz#ae25cf2512b3885a1d95d7f037868d8431124765"
-
 ms@2.0.0, ms@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
 
-multer@~1.3.0:
+multer@1.3.0:
   version "1.3.0"
   resolved "https://registry.yarnpkg.com/multer/-/multer-1.3.0.tgz#092b2670f6846fa4914965efc8cf94c20fec6cd2"
   dependencies:
@@ -4842,10 +5209,6 @@ multer@~1.3.0:
     type-is "^1.6.4"
     xtend "^4.0.0"
 
-muri@1.2.2:
-  version "1.2.2"
-  resolved "https://registry.yarnpkg.com/muri/-/muri-1.2.2.tgz#63198132650db08a04cc79ccd00dd389afd2631c"
-
 mustache@^2.3.0:
   version "2.3.0"
   resolved "https://registry.yarnpkg.com/mustache/-/mustache-2.3.0.tgz#4028f7778b17708a489930a6e52ac3bca0da41d0"
@@ -4862,7 +5225,7 @@ mv@~2:
     ncp "~2.0.0"
     rimraf "~2.4.0"
 
-nan@^2.3.0, nan@^2.3.2, nan@^2.3.3, nan@~2.6.1:
+nan@^2.3.0, nan@^2.3.2, nan@^2.3.3:
   version "2.6.2"
   resolved "https://registry.yarnpkg.com/nan/-/nan-2.6.2.tgz#e4ff34e6c95fdfb5aecc08de6596f43605a7db45"
 
@@ -4893,27 +5256,13 @@ negotiator@0.6.1:
   version "0.6.1"
   resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9"
 
-nested-error-stacks@^1.0.0:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/nested-error-stacks/-/nested-error-stacks-1.0.2.tgz#19f619591519f096769a5ba9a86e6eeec823c3cf"
-  dependencies:
-    inherits "~2.0.1"
-
-ngraminator@0.0.1:
-  version "0.0.1"
-  resolved "https://registry.yarnpkg.com/ngraminator/-/ngraminator-0.0.1.tgz#29cfd699df6970f42de9b2f0bdc7f4b60fad6f8e"
-
-node-2fa@~1.1.2:
+node-2fa@1.1.2:
   version "1.1.2"
   resolved "https://registry.yarnpkg.com/node-2fa/-/node-2fa-1.1.2.tgz#5bc5691474afe35ae6b3b76459b98b7c20c7158c"
   dependencies:
     notp "^2.0.3"
     thirty-two "0.0.2"
 
-node-abi@^2.0.0:
-  version "2.1.0"
-  resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.1.0.tgz#50ad834affcf17440e12bfc5f9ba0946f572d10c"
-
 node-fetch@1.6.3:
   version "1.6.3"
   resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.6.3.tgz#dc234edd6489982d58e8f0db4f695029abcd8c04"
@@ -4921,7 +5270,7 @@ node-fetch@1.6.3:
     encoding "^0.1.11"
     is-stream "^1.0.1"
 
-node-graceful@~0.2.3:
+node-graceful@0.2.3:
   version "0.2.3"
   resolved "https://registry.yarnpkg.com/node-graceful/-/node-graceful-0.2.3.tgz#ab120e1eed8c0c2b5e2ac874bf2754519c3fa942"
 
@@ -4970,7 +5319,7 @@ node-pre-gyp@^0.6.36:
     tar "^2.2.1"
     tar-pack "^3.4.0"
 
-node-sass@~4.5.3:
+node-sass@4.5.3:
   version "4.5.3"
   resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.5.3.tgz#d09c9d1179641239d1b97ffc6231fdcec53e1568"
   dependencies:
@@ -4997,24 +5346,20 @@ node-version@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/node-version/-/node-version-1.0.0.tgz#1b9b9584a9a7f7a6123f215cd14a652bf21ab19e"
 
-nodemon@~1.11.0:
-  version "1.11.0"
-  resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-1.11.0.tgz#226c562bd2a7b13d3d7518b49ad4828a3623d06c"
+nodemon@1.12.1:
+  version "1.12.1"
+  resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-1.12.1.tgz#996a56dc49d9f16bbf1b78a4de08f13634b3878d"
   dependencies:
-    chokidar "^1.4.3"
-    debug "^2.2.0"
-    es6-promise "^3.0.2"
-    ignore-by-default "^1.0.0"
+    chokidar "^1.7.0"
+    debug "^2.6.8"
+    es6-promise "^3.3.1"
+    ignore-by-default "^1.0.1"
     lodash.defaults "^3.1.2"
-    minimatch "^3.0.0"
-    ps-tree "^1.0.1"
-    touch "1.0.0"
+    minimatch "^3.0.4"
+    ps-tree "^1.1.0"
+    touch "^3.1.0"
     undefsafe "0.0.3"
-    update-notifier "0.5.0"
-
-noop-logger@^0.1.1:
-  version "0.1.1"
-  resolved "https://registry.yarnpkg.com/noop-logger/-/noop-logger-0.1.1.tgz#94a2b1633c4f1317553007d8966fd0e841b6a4c2"
+    update-notifier "^2.2.0"
 
 nopt@1.0.10, nopt@~1.0.10:
   version "1.0.10"
@@ -5050,6 +5395,10 @@ normalize-path@^2.0.1:
   dependencies:
     remove-trailing-separator "^1.0.1"
 
+normalize-range@^0.1.2:
+  version "0.1.2"
+  resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942"
+
 notp@^2.0.3:
   version "2.0.3"
   resolved "https://registry.yarnpkg.com/notp/-/notp-2.0.3.tgz#a9fd11e25cfe1ccb39fc6689544ee4c10ef9a577"
@@ -5060,7 +5409,7 @@ npm-run-path@^2.0.0:
   dependencies:
     path-key "^2.0.0"
 
-"npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.0.0, npmlog@^4.0.1, npmlog@^4.0.2:
+"npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.0.0, npmlog@^4.0.2:
   version "4.1.2"
   resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b"
   dependencies:
@@ -5082,6 +5431,10 @@ nth-check@~1.0.1:
   dependencies:
     boolbase "~1.0.0"
 
+num2fraction@^1.2.2:
+  version "1.2.2"
+  resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede"
+
 number-is-nan@^1.0.0:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
@@ -5090,7 +5443,7 @@ number-is-nan@^1.0.0:
   version "1.4.1"
   resolved "https://registry.yarnpkg.com/nwmatcher/-/nwmatcher-1.4.1.tgz#7ae9b07b0ea804db7e25f05cb5fe4097d4e4949f"
 
-oauth-sign@~0.8.1:
+oauth-sign@~0.8.1, oauth-sign@~0.8.2:
   version "0.8.2"
   resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43"
 
@@ -5098,17 +5451,25 @@ oauth@0.9.x:
   version "0.9.15"
   resolved "https://registry.yarnpkg.com/oauth/-/oauth-0.9.15.tgz#bd1fefaf686c96b75475aed5196412ff60cfb9c1"
 
+object-assign@4.1.0:
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.0.tgz#7a3b3d0e98063d43f4c03f2e8ae6cd51a86883a0"
+
 object-assign@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-3.0.0.tgz#9bedd5ca0897949bca47e7ff408062d549f587f2"
 
-object-assign@^4, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@~4.1.1:
+object-assign@^4, object-assign@^4.0.1, object-assign@^4.1.0:
   version "4.1.1"
   resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
 
-object-component@0.0.3:
-  version "0.0.3"
-  resolved "https://registry.yarnpkg.com/object-component/-/object-component-0.0.3.tgz#f0c69aa50efc95b866c186f400a33769cb2f1291"
+object-keys@^1.0.8:
+  version "1.0.11"
+  resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.11.tgz#c54601778ad560f1142ce0e01bcca8b56d13426d"
+
+object-path@^0.11.2:
+  version "0.11.4"
+  resolved "https://registry.yarnpkg.com/object-path/-/object-path-0.11.4.tgz#370ae752fbf37de3ea70a861c23bba8915691949"
 
 object.omit@^2.0.0:
   version "2.0.1"
@@ -5127,7 +5488,7 @@ on-headers@~1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.1.tgz#928f5d0f470d49342651ea6794b0857c100693f7"
 
-once@^1.3.0, once@^1.3.1, once@^1.3.3, once@^1.4.0:
+once@^1.3.0, once@^1.3.3, once@^1.4.0:
   version "1.4.0"
   resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
   dependencies:
@@ -5145,7 +5506,7 @@ onetime@^2.0.0:
   dependencies:
     mimic-fn "^1.0.0"
 
-opencollective@^1.0.3, opencollective@~1.0.3:
+opencollective@^1.0.3:
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/opencollective/-/opencollective-1.0.3.tgz#aee6372bc28144583690c3ca8daecfc120dd0ef1"
   dependencies:
@@ -5185,7 +5546,7 @@ options@>=0.0.5:
   version "0.0.6"
   resolved "https://registry.yarnpkg.com/options/-/options-0.0.6.tgz#ec22d312806bb53e731773e7cdaefcf1c643128f"
 
-ora@~1.3.0:
+ora@1.3.0:
   version "1.3.0"
   resolved "https://registry.yarnpkg.com/ora/-/ora-1.3.0.tgz#80078dd2b92a934af66a3ad72a5b910694ede51a"
   dependencies:
@@ -5194,7 +5555,7 @@ ora@~1.3.0:
     cli-spinners "^1.0.0"
     log-symbols "^1.0.2"
 
-os-homedir@^1.0.0, os-homedir@^1.0.1:
+os-homedir@^1.0.0:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3"
 
@@ -5216,7 +5577,7 @@ os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.1:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
 
-osenv@0, osenv@^0.1.0, osenv@^0.1.4:
+osenv@0, osenv@^0.1.4:
   version "0.1.4"
   resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.4.tgz#42fe6d5953df06c8064be6f176c3d05aaaa34644"
   dependencies:
@@ -5249,22 +5610,24 @@ p-locate@^2.0.0:
   dependencies:
     p-limit "^1.1.0"
 
-p-map@^1.1.1:
-  version "1.1.1"
-  resolved "https://registry.yarnpkg.com/p-map/-/p-map-1.1.1.tgz#05f5e4ae97a068371bc2a5cc86bfbdbc19c4ae7a"
-
 p-timeout@^1.1.1:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-1.2.0.tgz#9820f99434c5817868b4f34809ee5291660d5b6c"
   dependencies:
     p-finally "^1.0.0"
 
-package-json@^1.0.0:
-  version "1.2.0"
-  resolved "https://registry.yarnpkg.com/package-json/-/package-json-1.2.0.tgz#c8ecac094227cdf76a316874ed05e27cc939a0e0"
+package-json@^4.0.0:
+  version "4.0.1"
+  resolved "https://registry.yarnpkg.com/package-json/-/package-json-4.0.1.tgz#8869a0401253661c4c4ca3da6c2121ed555f5eed"
   dependencies:
-    got "^3.2.0"
-    registry-url "^3.0.0"
+    got "^6.7.1"
+    registry-auth-token "^3.0.1"
+    registry-url "^3.0.3"
+    semver "^5.1.0"
+
+packet-reader@0.3.1:
+  version "0.3.1"
+  resolved "https://registry.yarnpkg.com/packet-reader/-/packet-reader-0.3.1.tgz#cd62e60af8d7fea8a705ec4ff990871c46871f27"
 
 parse-bmfont-ascii@^1.0.3:
   version "1.0.6"
@@ -5313,53 +5676,39 @@ parse5@^3.0.1:
   dependencies:
     "@types/node" "^6.0.46"
 
-parsejson@0.0.3:
-  version "0.0.3"
-  resolved "https://registry.yarnpkg.com/parsejson/-/parsejson-0.0.3.tgz#ab7e3759f209ece99437973f7d0f1f64ae0e64ab"
-  dependencies:
-    better-assert "~1.0.0"
-
-parseqs@0.0.5:
-  version "0.0.5"
-  resolved "https://registry.yarnpkg.com/parseqs/-/parseqs-0.0.5.tgz#d5208a3738e46766e291ba2ea173684921a8b89d"
-  dependencies:
-    better-assert "~1.0.0"
-
-parseuri@0.0.5:
-  version "0.0.5"
-  resolved "https://registry.yarnpkg.com/parseuri/-/parseuri-0.0.5.tgz#80204a50d4dbb779bfdc6ebe2778d90e4bce320a"
-  dependencies:
-    better-assert "~1.0.0"
-
 parseurl@^1.3.0, parseurl@~1.3.1:
   version "1.3.1"
   resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.1.tgz#c8ab8c9223ba34888aa64a297b28853bec18da56"
 
+parseurl@~1.3.2:
+  version "1.3.2"
+  resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3"
+
 passport-azure-ad-oauth2@0.0.4:
   version "0.0.4"
   resolved "https://registry.yarnpkg.com/passport-azure-ad-oauth2/-/passport-azure-ad-oauth2-0.0.4.tgz#1a09d8869efd4afd095116e228941961b3a5c120"
   dependencies:
     passport-oauth "1.0.x"
 
-passport-facebook@~2.1.1:
+passport-facebook@2.1.1:
   version "2.1.1"
   resolved "https://registry.yarnpkg.com/passport-facebook/-/passport-facebook-2.1.1.tgz#c39d0b52ae4d59163245a4e21a7b9b6321303311"
   dependencies:
     passport-oauth2 "1.x.x"
 
-passport-github2@~0.1.10:
-  version "0.1.10"
-  resolved "https://registry.yarnpkg.com/passport-github2/-/passport-github2-0.1.10.tgz#50a21c1e95b83113e4da32c81c2c1a64429bb5bd"
+passport-github2@0.1.11:
+  version "0.1.11"
+  resolved "https://registry.yarnpkg.com/passport-github2/-/passport-github2-0.1.11.tgz#c92b56f3c38a44e766aac7e9e7c1384c5e93c999"
   dependencies:
     passport-oauth2 "1.x.x"
 
-passport-google-oauth20@~1.0.0:
+passport-google-oauth20@1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/passport-google-oauth20/-/passport-google-oauth20-1.0.0.tgz#3b960e8a1d70d1dbe794615c827c68c40392a5d0"
   dependencies:
     passport-oauth2 "1.x.x"
 
-passport-ldapauth@~2.0.0:
+passport-ldapauth@2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/passport-ldapauth/-/passport-ldapauth-2.0.0.tgz#42dff004417185d0a4d9f776a3eed8d4731fd689"
   dependencies:
@@ -5368,7 +5717,7 @@ passport-ldapauth@~2.0.0:
     ldapauth-fork "^4.0.1"
     passport-strategy "^1.0.0"
 
-passport-local@~1.0.0:
+passport-local@1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/passport-local/-/passport-local-1.0.0.tgz#1fe63268c92e75606626437e3b906662c15ba6ee"
   dependencies:
@@ -5417,17 +5766,18 @@ passport-strategy@1.x.x, passport-strategy@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/passport-strategy/-/passport-strategy-1.0.0.tgz#b5539aa8fc225a3d1ad179476ddf236b440f52e4"
 
-passport-windowslive@~1.0.2:
+passport-windowslive@1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/passport-windowslive/-/passport-windowslive-1.0.2.tgz#383cfee6589ffb5ecc2ad19c3a41ef691462a705"
   dependencies:
     passport-oauth2 "1.x.x"
 
-passport.socketio@~3.7.0:
-  version "3.7.0"
-  resolved "https://registry.yarnpkg.com/passport.socketio/-/passport.socketio-3.7.0.tgz#2ee5fafe9695d4281c8cddd3fe975ecd18e6726e"
+passport@0.4.0:
+  version "0.4.0"
+  resolved "https://registry.yarnpkg.com/passport/-/passport-0.4.0.tgz#c5095691347bd5ad3b5e180238c3914d16f05811"
   dependencies:
-    xtend "^4.0.0"
+    passport-strategy "1.x.x"
+    pause "0.0.1"
 
 passport@~0.1.1:
   version "0.1.18"
@@ -5436,13 +5786,6 @@ passport@~0.1.1:
     pause "0.0.1"
     pkginfo "0.2.x"
 
-passport@~0.4.0:
-  version "0.4.0"
-  resolved "https://registry.yarnpkg.com/passport/-/passport-0.4.0.tgz#c5095691347bd5ad3b5e180238c3914d16f05811"
-  dependencies:
-    passport-strategy "1.x.x"
-    pause "0.0.1"
-
 path-exists@^2.0.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b"
@@ -5501,6 +5844,85 @@ performance-now@^0.2.0:
   version "0.2.0"
   resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5"
 
+performance-now@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
+
+pg-connection-string@0.1.3:
+  version "0.1.3"
+  resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-0.1.3.tgz#da1847b20940e42ee1492beaf65d49d91b245df7"
+
+pg-hstore@2.3.2:
+  version "2.3.2"
+  resolved "https://registry.yarnpkg.com/pg-hstore/-/pg-hstore-2.3.2.tgz#f7ef053e7b9b892ae986af2f7cbe86432dfcf24f"
+  dependencies:
+    underscore "^1.7.0"
+
+pg-minify@~0.5.3:
+  version "0.5.3"
+  resolved "https://registry.yarnpkg.com/pg-minify/-/pg-minify-0.5.3.tgz#aa09befa3cbe29fab6461bf819100e0471215011"
+
+pg-pool@1.*:
+  version "1.8.0"
+  resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-1.8.0.tgz#f7ec73824c37a03f076f51bfdf70e340147c4f37"
+  dependencies:
+    generic-pool "2.4.3"
+    object-assign "4.1.0"
+
+pg-pool@~2.0.3:
+  version "2.0.3"
+  resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-2.0.3.tgz#c022032c8949f312a4f91fb6409ce04076be3257"
+
+pg-promise@6.10.3:
+  version "6.10.3"
+  resolved "https://registry.yarnpkg.com/pg-promise/-/pg-promise-6.10.3.tgz#1818d515f08757b6a1898ef2301438cfa4a3dcd7"
+  dependencies:
+    manakin "~0.5.1"
+    pg "~7.3.0"
+    pg-minify "~0.5.3"
+    spex "~2.0.0"
+
+pg-types@1.*, pg-types@~1.12.1:
+  version "1.12.1"
+  resolved "https://registry.yarnpkg.com/pg-types/-/pg-types-1.12.1.tgz#d64087e3903b58ffaad279e7595c52208a14c3d2"
+  dependencies:
+    postgres-array "~1.0.0"
+    postgres-bytea "~1.0.0"
+    postgres-date "~1.0.0"
+    postgres-interval "^1.1.0"
+
+pg@6.4.2:
+  version "6.4.2"
+  resolved "https://registry.yarnpkg.com/pg/-/pg-6.4.2.tgz#c364011060eac7a507a2ae063eb857ece910e27f"
+  dependencies:
+    buffer-writer "1.0.1"
+    js-string-escape "1.0.1"
+    packet-reader "0.3.1"
+    pg-connection-string "0.1.3"
+    pg-pool "1.*"
+    pg-types "1.*"
+    pgpass "1.*"
+    semver "4.3.2"
+
+pg@~7.3.0:
+  version "7.3.0"
+  resolved "https://registry.yarnpkg.com/pg/-/pg-7.3.0.tgz#275e27466e54a645f6b4a16f6acadf6b849ad83b"
+  dependencies:
+    buffer-writer "1.0.1"
+    js-string-escape "1.0.1"
+    packet-reader "0.3.1"
+    pg-connection-string "0.1.3"
+    pg-pool "~2.0.3"
+    pg-types "~1.12.1"
+    pgpass "1.x"
+    semver "4.3.2"
+
+pgpass@1.*, pgpass@1.x:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/pgpass/-/pgpass-1.0.2.tgz#2a7bb41b6065b67907e91da1b07c1847c877b306"
+  dependencies:
+    split "^1.0.0"
+
 pidusage@^1.1.0:
   version "1.1.5"
   resolved "https://registry.yarnpkg.com/pidusage/-/pidusage-1.1.5.tgz#b8c8d32bdfaf36212ca9e741028876ea33217e66"
@@ -5539,24 +5961,24 @@ pkginfo@0.2.x:
   version "0.2.3"
   resolved "https://registry.yarnpkg.com/pkginfo/-/pkginfo-0.2.3.tgz#7239c42a5ef6c30b8f328439d9b9ff71042490f8"
 
-pluralize@^4.0.0:
-  version "4.0.0"
-  resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-4.0.0.tgz#59b708c1c0190a2f692f1c7618c446b052fd1762"
+pluralize@^7.0.0:
+  version "7.0.0"
+  resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777"
 
-pm2-axon-rpc@0.4.5:
-  version "0.4.5"
-  resolved "https://registry.yarnpkg.com/pm2-axon-rpc/-/pm2-axon-rpc-0.4.5.tgz#fb62e9a53f3e2b7bed1afe16e3b0d1b06fe8ba69"
+pm2-axon-rpc@0.5.0:
+  version "0.5.0"
+  resolved "https://registry.yarnpkg.com/pm2-axon-rpc/-/pm2-axon-rpc-0.5.0.tgz#ad08d6a27f580d5c7be4d7bf9dddff398f868994"
   dependencies:
-    debug "*"
-    fclone "1.0.8"
+    debug "^3.0"
+    fclone "^1"
 
-pm2-axon@3.0.2:
-  version "3.0.2"
-  resolved "https://registry.yarnpkg.com/pm2-axon/-/pm2-axon-3.0.2.tgz#53de1d34edbf266d58f6b1dea2d8244c71ad24b9"
+pm2-axon@3.1.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/pm2-axon/-/pm2-axon-3.1.0.tgz#1b4527f3385e203adc1a5b0488bb52f0322731da"
   dependencies:
     amp "~0.3.1"
     amp-message "~0.1.1"
-    debug "~2.2.0"
+    debug "^3.0"
     escape-regexp "0.0.1"
 
 pm2-deploy@^0.3.5:
@@ -5572,9 +5994,9 @@ pm2-multimeter@^0.1.2:
   dependencies:
     charm "~0.1.1"
 
-pm2@~2.6.1:
-  version "2.6.1"
-  resolved "https://registry.yarnpkg.com/pm2/-/pm2-2.6.1.tgz#a9c2fdb7bf1676655935eb4176239003fca5c8da"
+pm2@2.7.1:
+  version "2.7.1"
+  resolved "https://registry.yarnpkg.com/pm2/-/pm2-2.7.1.tgz#b7b8404d8bec587526fd58bc21feffea351bec15"
   dependencies:
     async "^2.5"
     blessed "^0.1.81"
@@ -5583,7 +6005,7 @@ pm2@~2.6.1:
     cli-table-redemption "^1.0.0"
     commander "2.11.0"
     cron "1.2.1"
-    debug "^2.6"
+    debug "^3.0"
     eventemitter2 "1.0.5"
     fclone "1.0.11"
     mkdirp "0.5.1"
@@ -5591,26 +6013,26 @@ pm2@~2.6.1:
     needle "1.6.0"
     nssocket "0.6.0"
     pidusage "^1.1.0"
-    pm2-axon "3.0.2"
-    pm2-axon-rpc "0.4.5"
+    pm2-axon "3.1.0"
+    pm2-axon-rpc "0.5.0"
     pm2-deploy "^0.3.5"
     pm2-multimeter "^0.1.2"
-    pmx "^1.2.0"
+    pmx "~1.5.0"
     promptly "2.2.0"
     semver "^5.3"
     shelljs "0.7.8"
-    source-map-support "^0.4.15"
+    source-map-support "^0.4.18"
     sprintf-js "1.1.1"
     vizion "^0.2"
     yamljs "0.3.0"
   optionalDependencies:
     gkt "https://tgz.pm2.io/gkt-1.0.0.tgz"
 
-pmx@^1.2.0:
-  version "1.2.0"
-  resolved "https://registry.yarnpkg.com/pmx/-/pmx-1.2.0.tgz#712a9e1fdea53a9b061169cc7676b14838c87585"
+pmx@~1.5.0:
+  version "1.5.4"
+  resolved "https://registry.yarnpkg.com/pmx/-/pmx-1.5.4.tgz#27d71c54e727b5186485545b9c70c21eabc81c0f"
   dependencies:
-    debug "^2.6"
+    debug "^3"
     json-stringify-safe "^5.0"
     vxx "^1.2.0"
 
@@ -5618,6 +6040,18 @@ pngjs@^3.0.0:
   version "3.2.0"
   resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-3.2.0.tgz#fc9fcea1a8a375da54a51148019d5abd41dbabde"
 
+postcss-selector-parser@2.2.3:
+  version "2.2.3"
+  resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-2.2.3.tgz#f9437788606c3c9acee16ffe8d8b16297f27bb90"
+  dependencies:
+    flatten "^1.0.2"
+    indexes-of "^1.0.1"
+    uniq "^1.0.1"
+
+postcss-value-parser@^3.2.3:
+  version "3.3.0"
+  resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz#87f38f9f18f774a4ab4c8a232f5c5ce8872a9d15"
+
 postcss@^6.0.1:
   version "6.0.8"
   resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.8.tgz#89067a9ce8b11f8a84cbc5117efc30419a0857b3"
@@ -5626,24 +6060,31 @@ postcss@^6.0.1:
     source-map "^0.5.6"
     supports-color "^4.2.0"
 
-prebuild-install@^2.1.0:
-  version "2.2.0"
-  resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-2.2.0.tgz#55934756a32bac8747390ca44ff663cee8b99b69"
+postcss@^6.0.13:
+  version "6.0.13"
+  resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.13.tgz#b9ecab4ee00c89db3ec931145bd9590bbf3f125f"
   dependencies:
-    expand-template "^1.0.2"
-    github-from-package "0.0.0"
-    minimist "^1.2.0"
-    mkdirp "^0.5.1"
-    node-abi "^2.0.0"
-    noop-logger "^0.1.1"
-    npmlog "^4.0.1"
-    os-homedir "^1.0.1"
-    pump "^1.0.1"
-    rc "^1.1.6"
-    simple-get "^1.4.2"
-    tar-fs "^1.13.0"
-    tunnel-agent "^0.6.0"
-    xtend "4.0.1"
+    chalk "^2.1.0"
+    source-map "^0.6.1"
+    supports-color "^4.4.0"
+
+postgres-array@~1.0.0:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/postgres-array/-/postgres-array-1.0.2.tgz#8e0b32eb03bf77a5c0a7851e0441c169a256a238"
+
+postgres-bytea@~1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/postgres-bytea/-/postgres-bytea-1.0.0.tgz#027b533c0aa890e26d172d47cf9ccecc521acd35"
+
+postgres-date@~1.0.0:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/postgres-date/-/postgres-date-1.0.3.tgz#e2d89702efdb258ff9d9cee0fe91bd06975257a8"
+
+postgres-interval@^1.1.0:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/postgres-interval/-/postgres-interval-1.1.1.tgz#acdb0f897b4b1c6e496d9d4e0a853e1c428f06f0"
+  dependencies:
+    xtend "^4.0.0"
 
 precond@0.2:
   version "0.2.3"
@@ -5653,7 +6094,7 @@ prelude-ls@~1.1.2:
   version "1.1.2"
   resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
 
-prepend-http@^1.0.0, prepend-http@^1.0.1:
+prepend-http@^1.0.1:
   version "1.0.4"
   resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc"
 
@@ -5661,12 +6102,12 @@ preserve@^0.2.0:
   version "0.2.0"
   resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b"
 
-pretty-format@^20.0.3:
-  version "20.0.3"
-  resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-20.0.3.tgz#020e350a560a1fe1a98dc3beb6ccffb386de8b14"
+pretty-format@^21.2.1:
+  version "21.2.1"
+  resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-21.2.1.tgz#ae5407f3cf21066cd011aa1ba5fce7b6a2eddb36"
   dependencies:
-    ansi-regex "^2.1.1"
-    ansi-styles "^3.0.0"
+    ansi-regex "^3.0.0"
+    ansi-styles "^3.2.0"
 
 pretty-time@^0.2.0:
   version "0.2.0"
@@ -5729,22 +6170,18 @@ proxy-addr@~1.1.4:
     forwarded "~0.1.0"
     ipaddr.js "1.3.0"
 
-proxy-addr@~1.1.5:
-  version "1.1.5"
-  resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-1.1.5.tgz#71c0ee3b102de3f202f3b64f608d173fcba1a918"
+proxy-addr@~2.0.2:
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.2.tgz#6571504f47bb988ec8180253f85dd7e14952bdec"
   dependencies:
-    forwarded "~0.1.0"
-    ipaddr.js "1.4.0"
+    forwarded "~0.1.2"
+    ipaddr.js "1.5.2"
 
 prr@~0.0.0:
   version "0.0.0"
   resolved "https://registry.yarnpkg.com/prr/-/prr-0.0.0.tgz#1a84b85908325501411853d0081ee3fa86e2926a"
 
-prr@~1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476"
-
-ps-tree@^1.0.1:
+ps-tree@^1.1.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/ps-tree/-/ps-tree-1.1.0.tgz#b421b24140d6203f1ed3c76996b4427b08e8c014"
   dependencies:
@@ -5762,9 +6199,9 @@ pug-attrs@^2.0.1, pug-attrs@^2.0.2:
     js-stringify "^1.0.1"
     pug-runtime "^2.0.3"
 
-pug-code-gen@^1.1.1:
-  version "1.1.1"
-  resolved "https://registry.yarnpkg.com/pug-code-gen/-/pug-code-gen-1.1.1.tgz#1cf72744ef2a039eae6a3340caaa1105871258e8"
+pug-code-gen@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/pug-code-gen/-/pug-code-gen-2.0.0.tgz#96aea39a9e62f1ec5d2b6a5b42a29d528c70b43d"
   dependencies:
     constantinople "^3.0.1"
     doctypes "^1.1.0"
@@ -5779,15 +6216,15 @@ pug-error@^1.3.0, pug-error@^1.3.2:
   version "1.3.2"
   resolved "https://registry.yarnpkg.com/pug-error/-/pug-error-1.3.2.tgz#53ae7d9d29bb03cf564493a026109f54c47f5f26"
 
-pug-filters@^2.1.4:
-  version "2.1.4"
-  resolved "https://registry.yarnpkg.com/pug-filters/-/pug-filters-2.1.4.tgz#ab247c0f58765414b61be7b54fe979e9f6fc898f"
+pug-filters@^2.1.5:
+  version "2.1.5"
+  resolved "https://registry.yarnpkg.com/pug-filters/-/pug-filters-2.1.5.tgz#66bf6e80d97fbef829bab0aa35eddff33fc964f3"
   dependencies:
     clean-css "^3.3.0"
     constantinople "^3.0.1"
     jstransformer "1.0.0"
     pug-error "^1.3.2"
-    pug-walk "^1.1.4"
+    pug-walk "^1.1.5"
     resolve "^1.1.6"
     uglify-js "^2.6.1"
 
@@ -5807,16 +6244,16 @@ pug-lexer@^3.1.0:
     is-expression "^3.0.0"
     pug-error "^1.3.2"
 
-pug-linker@^3.0.2:
-  version "3.0.2"
-  resolved "https://registry.yarnpkg.com/pug-linker/-/pug-linker-3.0.2.tgz#cc0780cf9f3f5522b270871785492b99588d3142"
+pug-linker@^3.0.3:
+  version "3.0.3"
+  resolved "https://registry.yarnpkg.com/pug-linker/-/pug-linker-3.0.3.tgz#25f59eb750237f0368e59c3379764229c0189c41"
   dependencies:
     pug-error "^1.3.2"
-    pug-walk "^1.1.4"
+    pug-walk "^1.1.5"
 
-pug-lint@~2.4.0:
-  version "2.4.0"
-  resolved "https://registry.yarnpkg.com/pug-lint/-/pug-lint-2.4.0.tgz#1f584c1624fac48e5a0d03e40823caef736702e0"
+pug-lint@2.5.0:
+  version "2.5.0"
+  resolved "https://registry.yarnpkg.com/pug-lint/-/pug-lint-2.5.0.tgz#4419ee301aeca45f54061b0eca4a9a471f3aa9a9"
   dependencies:
     acorn "^4.0.1"
     commander "^2.9.0"
@@ -5832,16 +6269,16 @@ pug-lint@~2.4.0:
     strip-json-comments "^2.0.1"
     void-elements "^2.0.1"
 
-pug-load@^2.0.8:
-  version "2.0.8"
-  resolved "https://registry.yarnpkg.com/pug-load/-/pug-load-2.0.8.tgz#1df1c1716f3e68c70d71699cff9458472dc38b9b"
+pug-load@^2.0.9:
+  version "2.0.9"
+  resolved "https://registry.yarnpkg.com/pug-load/-/pug-load-2.0.9.tgz#ee217c914cc1d9324d44b86c32d1df241d36de7a"
   dependencies:
     object-assign "^4.1.0"
-    pug-walk "^1.1.4"
+    pug-walk "^1.1.5"
 
-pug-parser@^3.0.1:
-  version "3.0.1"
-  resolved "https://registry.yarnpkg.com/pug-parser/-/pug-parser-3.0.1.tgz#dc0c5dd6c9c2d89da6105abbdf3d1b0fb4d39b5e"
+pug-parser@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/pug-parser/-/pug-parser-4.0.0.tgz#c9f52322e4eabe4bf5beeba64ed18373bb627801"
   dependencies:
     pug-error "^1.3.2"
     token-stream "0.0.1"
@@ -5856,38 +6293,23 @@ pug-strip-comments@^1.0.2:
   dependencies:
     pug-error "^1.3.2"
 
-pug-walk@^1.1.4:
-  version "1.1.4"
-  resolved "https://registry.yarnpkg.com/pug-walk/-/pug-walk-1.1.4.tgz#29e5174af43b67e99c31b448632e1ff86ddd671c"
+pug-walk@^1.1.5:
+  version "1.1.5"
+  resolved "https://registry.yarnpkg.com/pug-walk/-/pug-walk-1.1.5.tgz#90e943acbcf7021e6454cf1b32245891cba6f851"
 
-pug@~2.0.0-rc.3:
-  version "2.0.0-rc.3"
-  resolved "https://registry.yarnpkg.com/pug/-/pug-2.0.0-rc.3.tgz#553cb3c3a97bb54ec3cb1e08591dcae3b6f58891"
+pug@2.0.0-rc.4:
+  version "2.0.0-rc.4"
+  resolved "https://registry.yarnpkg.com/pug/-/pug-2.0.0-rc.4.tgz#b7b08f6599bd5302568042b7436984fb28c80a13"
   dependencies:
-    pug-code-gen "^1.1.1"
-    pug-filters "^2.1.4"
+    pug-code-gen "^2.0.0"
+    pug-filters "^2.1.5"
     pug-lexer "^3.1.0"
-    pug-linker "^3.0.2"
-    pug-load "^2.0.8"
-    pug-parser "^3.0.1"
+    pug-linker "^3.0.3"
+    pug-load "^2.0.9"
+    pug-parser "^4.0.0"
     pug-runtime "^2.0.3"
     pug-strip-comments "^1.0.2"
 
-pump@^1.0.0, pump@^1.0.1:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/pump/-/pump-1.0.2.tgz#3b3ee6512f94f0e575538c17995f9f16990a5d51"
-  dependencies:
-    end-of-stream "^1.1.0"
-    once "^1.3.1"
-
-pumpify@^1.3.5:
-  version "1.3.5"
-  resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.3.5.tgz#1b671c619940abcaeac0ad0e3a3c164be760993b"
-  dependencies:
-    duplexify "^3.1.2"
-    inherits "^2.0.1"
-    pump "^1.0.0"
-
 punycode@^1.4.1:
   version "1.4.1"
   resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
@@ -5896,6 +6318,10 @@ q@^1.1.2:
   version "1.5.0"
   resolved "https://registry.yarnpkg.com/q/-/q-1.5.0.tgz#dd01bac9d06d30e6f219aecb8253ee9ebdc308f1"
 
+qr-image@3.2.0:
+  version "3.2.0"
+  resolved "https://registry.yarnpkg.com/qr-image/-/qr-image-3.2.0.tgz#9fa8295beae50c4a149cf9f909a1db464a8672e8"
+
 qs@4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/qs/-/qs-4.0.0.tgz#c31d9b74ec27df75e543a86c78728ed8d4623607"
@@ -5904,9 +6330,9 @@ qs@6.4.0, qs@~6.4.0:
   version "6.4.0"
   resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233"
 
-qs@6.5.0:
-  version "6.5.0"
-  resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.0.tgz#8d04954d364def3efc55b5a0793e1e2c8b1e6e49"
+qs@6.5.1, qs@~6.5.1:
+  version "6.5.1"
+  resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8"
 
 random-bytes@~1.0.0:
   version "1.0.0"
@@ -5927,6 +6353,15 @@ range-parser@~1.2.0:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e"
 
+raw-body@2.3.2:
+  version "2.3.2"
+  resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.2.tgz#bcd60c77d3eb93cde0050295c3f379389bc88f89"
+  dependencies:
+    bytes "3.0.0"
+    http-errors "1.6.2"
+    iconv-lite "0.4.19"
+    unpipe "1.0.0"
+
 raw-body@~2.2.0:
   version "2.2.0"
   resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.2.0.tgz#994976cf6a5096a41162840492f0bdc5d6e7fb96"
@@ -5944,24 +6379,17 @@ rc@^1.0.1, rc@^1.1.6, rc@^1.1.7:
     minimist "^1.2.0"
     strip-json-comments "~2.0.1"
 
-read-all-stream@^3.0.0:
-  version "3.1.0"
-  resolved "https://registry.yarnpkg.com/read-all-stream/-/read-all-stream-3.1.0.tgz#35c3e177f2078ef789ee4bfafa4373074eaef4fa"
-  dependencies:
-    pinkie-promise "^2.0.0"
-    readable-stream "^2.0.0"
-
-read-chunk@^1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/read-chunk/-/read-chunk-1.0.1.tgz#5f68cab307e663f19993527d9b589cace4661194"
-
-read-chunk@~2.1.0:
+read-chunk@2.1.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/read-chunk/-/read-chunk-2.1.0.tgz#6a04c0928005ed9d42e1a6ac5600e19cbc7ff655"
   dependencies:
     pify "^3.0.0"
     safe-buffer "^5.1.1"
 
+read-chunk@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/read-chunk/-/read-chunk-1.0.1.tgz#5f68cab307e663f19993527d9b589cace4661194"
+
 read-pkg-up@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02"
@@ -5998,7 +6426,7 @@ read@^1.0.4:
   dependencies:
     mute-stream "~0.0.4"
 
-readable-stream@1.1.x, readable-stream@^1.0.33:
+readable-stream@1.1.x:
   version "1.1.14"
   resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9"
   dependencies:
@@ -6007,19 +6435,7 @@ readable-stream@1.1.x, readable-stream@^1.0.33:
     isarray "0.0.1"
     string_decoder "~0.10.x"
 
-readable-stream@2.2.7:
-  version "2.2.7"
-  resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.7.tgz#07057acbe2467b22042d36f98c5ad507054e95b1"
-  dependencies:
-    buffer-shims "~1.0.0"
-    core-util-is "~1.0.0"
-    inherits "~2.0.1"
-    isarray "~1.0.0"
-    process-nextick-args "~1.0.6"
-    string_decoder "~1.0.0"
-    util-deprecate "~1.0.1"
-
-readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.1.5, readable-stream@^2.2.2:
+readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.1.5, readable-stream@^2.2.2:
   version "2.3.3"
   resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c"
   dependencies:
@@ -6060,10 +6476,39 @@ redent@^1.0.0:
     indent-string "^2.1.0"
     strip-indent "^1.0.1"
 
+redis-commands@^1.2.0:
+  version "1.3.1"
+  resolved "https://registry.yarnpkg.com/redis-commands/-/redis-commands-1.3.1.tgz#81d826f45fa9c8b2011f4cd7a0fe597d241d442b"
+
+redis-parser@^2.4.0, redis-parser@^2.5.0:
+  version "2.6.0"
+  resolved "https://registry.yarnpkg.com/redis-parser/-/redis-parser-2.6.0.tgz#52ed09dacac108f1a631c07e9b69941e7a19504b"
+
+redis@^2.1.0:
+  version "2.7.1"
+  resolved "https://registry.yarnpkg.com/redis/-/redis-2.7.1.tgz#7d56f7875b98b20410b71539f1d878ed58ebf46a"
+  dependencies:
+    double-ended-queue "^2.1.0-0"
+    redis-commands "^1.2.0"
+    redis-parser "^2.5.0"
+
+redis@~0.10.0:
+  version "0.10.3"
+  resolved "https://registry.yarnpkg.com/redis/-/redis-0.10.3.tgz#8927fe2110ee39617bcf3fd37b89d8e123911bb6"
+
 reduce-flatten@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/reduce-flatten/-/reduce-flatten-1.0.1.tgz#258c78efd153ddf93cb561237f61184f3696e327"
 
+redux@^3.4.0:
+  version "3.7.2"
+  resolved "https://registry.yarnpkg.com/redux/-/redux-3.7.2.tgz#06b73123215901d25d065be342eb026bc1c8537b"
+  dependencies:
+    lodash "^4.2.1"
+    lodash-es "^4.2.1"
+    loose-envify "^1.1.0"
+    symbol-observable "^1.0.3"
+
 regenerate@^1.2.1:
   version "1.3.2"
   resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.3.2.tgz#d1941c67bad437e1be76433add5b385f95b19260"
@@ -6084,6 +6529,14 @@ regenerator-transform@0.9.11:
     babel-types "^6.19.0"
     private "^0.1.6"
 
+regenerator-transform@^0.10.0:
+  version "0.10.1"
+  resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd"
+  dependencies:
+    babel-runtime "^6.18.0"
+    babel-types "^6.19.0"
+    private "^0.1.6"
+
 regex-cache@^0.4.2:
   version "0.4.3"
   resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.3.tgz#9b1a6c35d4d0dfcef5711ae651e8e9d3d7114145"
@@ -6091,10 +6544,6 @@ regex-cache@^0.4.2:
     is-equal-shallow "^0.1.3"
     is-primitive "^2.0.0"
 
-regexp-clone@0.0.1:
-  version "0.0.1"
-  resolved "https://registry.yarnpkg.com/regexp-clone/-/regexp-clone-0.0.1.tgz#a7c2e09891fdbf38fbb10d376fb73003e68ac589"
-
 regexpu-core@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240"
@@ -6103,7 +6552,14 @@ regexpu-core@^2.0.0:
     regjsgen "^0.2.0"
     regjsparser "^0.1.4"
 
-registry-url@^3.0.0:
+registry-auth-token@^3.0.1:
+  version "3.3.1"
+  resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-3.3.1.tgz#fb0d3289ee0d9ada2cbb52af5dfe66cb070d3006"
+  dependencies:
+    rc "^1.1.6"
+    safe-buffer "^5.0.1"
+
+registry-url@^3.0.3:
   version "3.1.0"
   resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-3.1.0.tgz#3d4ef870f73dde1d77f0cf9a381432444e174942"
   dependencies:
@@ -6119,7 +6575,7 @@ regjsparser@^0.1.4:
   dependencies:
     jsesc "~0.5.0"
 
-remove-markdown@~0.2.2:
+remove-markdown@0.2.2:
   version "0.2.2"
   resolved "https://registry.yarnpkg.com/remove-markdown/-/remove-markdown-0.2.2.tgz#66b0ceeba9fb77ca9636bb1b0307ce21a32a12a6"
 
@@ -6135,19 +6591,13 @@ repeat-string@^1.5.2:
   version "1.6.1"
   resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637"
 
-repeating@^1.1.2:
-  version "1.1.3"
-  resolved "https://registry.yarnpkg.com/repeating/-/repeating-1.1.3.tgz#3d4114218877537494f97f77f9785fab810fa4ac"
-  dependencies:
-    is-finite "^1.0.0"
-
 repeating@^2.0.0:
   version "2.0.1"
   resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda"
   dependencies:
     is-finite "^1.0.0"
 
-request@2, request@^2.65.0, request@^2.67.0, request@^2.79.0, request@^2.81.0, request@~2.81.0:
+request@2, request@^2.65.0, request@^2.67.0, request@^2.79.0, request@^2.81.0:
   version "2.81.0"
   resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0"
   dependencies:
@@ -6174,6 +6624,33 @@ request@2, request@^2.65.0, request@^2.67.0, request@^2.79.0, request@^2.81.0, r
     tunnel-agent "^0.6.0"
     uuid "^3.0.0"
 
+request@2.83.0:
+  version "2.83.0"
+  resolved "https://registry.yarnpkg.com/request/-/request-2.83.0.tgz#ca0b65da02ed62935887808e6f510381034e3356"
+  dependencies:
+    aws-sign2 "~0.7.0"
+    aws4 "^1.6.0"
+    caseless "~0.12.0"
+    combined-stream "~1.0.5"
+    extend "~3.0.1"
+    forever-agent "~0.6.1"
+    form-data "~2.3.1"
+    har-validator "~5.0.3"
+    hawk "~6.0.2"
+    http-signature "~1.2.0"
+    is-typedarray "~1.0.0"
+    isstream "~0.1.2"
+    json-stringify-safe "~5.0.1"
+    mime-types "~2.1.17"
+    oauth-sign "~0.8.2"
+    performance-now "^2.1.0"
+    qs "~6.5.1"
+    safe-buffer "^5.1.1"
+    stringstream "~0.0.5"
+    tough-cookie "~2.3.3"
+    tunnel-agent "^0.6.0"
+    uuid "^3.1.0"
+
 require-directory@^2.1.1:
   version "2.1.1"
   resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
@@ -6189,26 +6666,15 @@ require-uncached@^1.0.3:
     caller-path "^0.1.0"
     resolve-from "^1.0.0"
 
-require_optional@~1.0.0:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/require_optional/-/require_optional-1.0.1.tgz#4cf35a4247f64ca3df8c2ef208cc494b1ca8fc2e"
-  dependencies:
-    resolve-from "^2.0.0"
-    semver "^5.1.0"
-
 resolve-from@^1.0.0:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226"
 
-resolve-from@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-2.0.0.tgz#9480ab20e94ffa1d9e80a804c7ea147611966b57"
-
 resolve@1.1.7:
   version "1.1.7"
   resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b"
 
-resolve@^1.1.6, resolve@^1.1.7, resolve@^1.2.0, resolve@^1.3.2, resolve@^1.3.3:
+resolve@^1.1.6, resolve@^1.1.7, resolve@^1.2.0, resolve@^1.3.3:
   version "1.3.3"
   resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.3.3.tgz#655907c3469a8680dc2de3a275a8fdd69691f0e5"
   dependencies:
@@ -6221,6 +6687,17 @@ restore-cursor@^2.0.0:
     onetime "^2.0.0"
     signal-exit "^3.0.2"
 
+retry-as-promised@^2.3.1:
+  version "2.3.1"
+  resolved "https://registry.yarnpkg.com/retry-as-promised/-/retry-as-promised-2.3.1.tgz#f75059183f9730771c09bad1eed57537931cbc9d"
+  dependencies:
+    bluebird "^3.4.6"
+    debug "^2.2.0"
+
+retry@0.6.0:
+  version "0.6.0"
+  resolved "https://registry.yarnpkg.com/retry/-/retry-0.6.0.tgz#1c010713279a6fd1e8def28af0c3ff1871caa537"
+
 right-align@^0.1.1:
   version "0.1.3"
   resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef"
@@ -6259,10 +6736,6 @@ rx@^4.1.0:
   version "4.1.0"
   resolved "https://registry.yarnpkg.com/rx/-/rx-4.1.0.tgz#a5f13ff79ef3b740fe30aa803fb09f98805d4782"
 
-safe-buffer@5.0.1, safe-buffer@~5.0.1:
-  version "5.0.1"
-  resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.0.1.tgz#d263ca54696cd8a306b5ca6551e92de57918fbe7"
-
 safe-buffer@5.1.1, safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
   version "5.1.1"
   resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853"
@@ -6271,17 +6744,19 @@ safe-json-stringify@~1:
   version "1.0.4"
   resolved "https://registry.yarnpkg.com/safe-json-stringify/-/safe-json-stringify-1.0.4.tgz#81a098f447e4bbc3ff3312a243521bc060ef5911"
 
-sane@~1.6.0:
-  version "1.6.0"
-  resolved "https://registry.yarnpkg.com/sane/-/sane-1.6.0.tgz#9610c452307a135d29c1fdfe2547034180c46775"
+sane@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/sane/-/sane-2.0.0.tgz#99cb79f21f4a53a69d4d0cd957c2db04024b8eb2"
   dependencies:
     anymatch "^1.3.0"
     exec-sh "^0.2.0"
-    fb-watchman "^1.8.0"
+    fb-watchman "^2.0.0"
     minimatch "^3.0.2"
     minimist "^1.1.1"
     walker "~1.0.5"
     watch "~0.10.0"
+  optionalDependencies:
+    fsevents "^1.1.1"
 
 sass-graph@^2.1.1:
   version "2.2.4"
@@ -6303,36 +6778,6 @@ scss-tokenizer@^0.2.3:
     js-base64 "^2.1.8"
     source-map "^0.4.2"
 
-search-index-adder@~0.3.9:
-  version "0.3.9"
-  resolved "https://registry.yarnpkg.com/search-index-adder/-/search-index-adder-0.3.9.tgz#a94b5fc5b27f1827c43eab599c760dcc4c29599d"
-  dependencies:
-    JSONStream "^1.2.1"
-    async "^2.3.0"
-    bunyan "^1.8.10"
-    docproc "^1.0.0"
-    levelup "^1.3.8"
-    pumpify "^1.3.5"
-  optionalDependencies:
-    leveldown "^1.7.1"
-
-search-index-searcher@~0.2.10:
-  version "0.2.10"
-  resolved "https://registry.yarnpkg.com/search-index-searcher/-/search-index-searcher-0.2.10.tgz#3b52b8bb643065883997dfce57c6c792ec551cb0"
-  dependencies:
-    bunyan "^1.8.1"
-    intersect-arrays-to-stream "^0.0.3"
-    levelup "^1.3.8"
-    lodash.difference "^4.5.0"
-    lodash.intersection "^4.4.0"
-    lodash.sortedindexof "^4.1.0"
-    lodash.spread "^4.2.1"
-    lodash.union "^4.6.0"
-    lodash.uniq "^4.5.0"
-    ngraminator "0.0.1"
-  optionalDependencies:
-    leveldown "^1.6.0"
-
 select@^1.1.2:
   version "1.1.2"
   resolved "https://registry.yarnpkg.com/select/-/select-1.1.2.tgz#0e7350acdec80b1108528786ec1d4418d11b396d"
@@ -6347,11 +6792,11 @@ semver-diff@^2.0.0:
   version "5.3.0"
   resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f"
 
-semver@~5.1.0:
-  version "5.1.1"
-  resolved "https://registry.yarnpkg.com/semver/-/semver-5.1.1.tgz#a3292a373e6f3e0798da0b20641b9a9c5bc47e19"
+semver@4.3.2:
+  version "4.3.2"
+  resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.2.tgz#c7a07158a80bedd052355b770d82d6640f803be7"
 
-semver@~5.4.1:
+semver@5.4.1, semver@^5.4.1:
   version "5.4.1"
   resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e"
 
@@ -6407,33 +6852,55 @@ send@0.15.3:
     range-parser "~1.2.0"
     statuses "~1.3.1"
 
-send@0.15.4:
-  version "0.15.4"
-  resolved "https://registry.yarnpkg.com/send/-/send-0.15.4.tgz#985faa3e284b0273c793364a35c6737bd93905b9"
+send@0.16.1:
+  version "0.16.1"
+  resolved "https://registry.yarnpkg.com/send/-/send-0.16.1.tgz#a70e1ca21d1382c11d0d9f6231deb281080d7ab3"
   dependencies:
-    debug "2.6.8"
+    debug "2.6.9"
     depd "~1.1.1"
     destroy "~1.0.4"
     encodeurl "~1.0.1"
     escape-html "~1.0.3"
-    etag "~1.8.0"
-    fresh "0.5.0"
+    etag "~1.8.1"
+    fresh "0.5.2"
     http-errors "~1.6.2"
-    mime "1.3.4"
+    mime "1.4.1"
     ms "2.0.0"
     on-finished "~2.3.0"
     range-parser "~1.2.0"
     statuses "~1.3.1"
 
-serve-favicon@~2.4.3:
-  version "2.4.3"
-  resolved "https://registry.yarnpkg.com/serve-favicon/-/serve-favicon-2.4.3.tgz#5986b17b0502642b641c21f818b1acce32025d23"
+sequelize@4.13.5:
+  version "4.13.5"
+  resolved "https://registry.yarnpkg.com/sequelize/-/sequelize-4.13.5.tgz#f3a397858c2821da5384e51b4eb98a9ff65ecb16"
   dependencies:
-    etag "~1.8.0"
-    fresh "0.5.0"
+    bluebird "^3.4.6"
+    cls-bluebird "^2.0.1"
+    debug "^3.0.0"
+    depd "^1.1.0"
+    dottie "^2.0.0"
+    generic-pool "^3.1.8"
+    inflection "1.12.0"
+    lodash "^4.17.1"
+    moment "^2.13.0"
+    moment-timezone "^0.5.4"
+    retry-as-promised "^2.3.1"
+    semver "^5.0.1"
+    terraformer-wkt-parser "^1.1.2"
+    toposort-class "^1.0.1"
+    uuid "^3.0.0"
+    validator "^8.0.0"
+    wkx "^0.4.1"
+
+serve-favicon@2.4.5:
+  version "2.4.5"
+  resolved "https://registry.yarnpkg.com/serve-favicon/-/serve-favicon-2.4.5.tgz#49d9a46863153a9240691c893d2b0e7d85d6d436"
+  dependencies:
+    etag "~1.8.1"
+    fresh "0.5.2"
     ms "2.0.0"
-    parseurl "~1.3.1"
-    safe-buffer "5.0.1"
+    parseurl "~1.3.2"
+    safe-buffer "5.1.1"
 
 serve-static@1.12.3:
   version "1.12.3"
@@ -6444,14 +6911,14 @@ serve-static@1.12.3:
     parseurl "~1.3.1"
     send "0.15.3"
 
-serve-static@1.12.4:
-  version "1.12.4"
-  resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.12.4.tgz#9b6aa98eeb7253c4eedc4c1f6fdbca609901a961"
+serve-static@1.13.1:
+  version "1.13.1"
+  resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.13.1.tgz#4c57d53404a761d8f2e7c1e8a18a47dbf278a719"
   dependencies:
     encodeurl "~1.0.1"
     escape-html "~1.0.3"
-    parseurl "~1.3.1"
-    send "0.15.4"
+    parseurl "~1.3.2"
+    send "0.16.1"
 
 serve-static@~1.10.2:
   version "1.10.3"
@@ -6473,6 +6940,10 @@ setprototypeof@1.0.3:
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.0.3.tgz#66567e37043eeb4f04d91bd658c0cbefb55b8e04"
 
+setprototypeof@1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656"
+
 shebang-command@^1.2.0:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
@@ -6511,15 +6982,15 @@ signal-exit@^3.0.0, signal-exit@^3.0.2:
   version "3.0.2"
   resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
 
-simple-get@^1.4.2:
-  version "1.4.3"
-  resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-1.4.3.tgz#e9755eda407e96da40c5e5158c9ea37b33becbeb"
-  dependencies:
-    once "^1.3.1"
-    unzip-response "^1.0.0"
-    xtend "^4.0.0"
+simple-breakpoints@^1.1.1:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/simple-breakpoints/-/simple-breakpoints-1.1.2.tgz#2a690bb989228bc1f80acf802785f61f53ed6b92"
 
-simplemde@~1.11.2:
+simple-lru-cache@0.0.x:
+  version "0.0.2"
+  resolved "https://registry.yarnpkg.com/simple-lru-cache/-/simple-lru-cache-0.0.2.tgz#d59cc3a193c1a5d0320f84ee732f6e4713e511dd"
+
+simplemde@1.11.2:
   version "1.11.2"
   resolved "https://registry.yarnpkg.com/simplemde/-/simplemde-1.11.2.tgz#a23a35d978d2c40ef07dec008c92f070d8e080e3"
   dependencies:
@@ -6535,67 +7006,17 @@ slice-ansi@0.0.4:
   version "0.0.4"
   resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35"
 
-sliced@0.0.5:
-  version "0.0.5"
-  resolved "https://registry.yarnpkg.com/sliced/-/sliced-0.0.5.tgz#5edc044ca4eb6f7816d50ba2fc63e25d8fe4707f"
-
-sliced@1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/sliced/-/sliced-1.0.1.tgz#0b3a662b5d04c3177b1926bea82b03f837a2ef41"
-
-slide@^1.1.5:
-  version "1.1.6"
-  resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707"
-
 sntp@1.x.x:
   version "1.0.9"
   resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198"
   dependencies:
     hoek "2.x.x"
 
-socket.io-adapter@~1.1.0:
-  version "1.1.0"
-  resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-1.1.0.tgz#c7aa46501dd556c2cb8a28af8ff95c0b5e1daa4c"
+sntp@2.x.x:
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/sntp/-/sntp-2.0.2.tgz#5064110f0af85f7cfdb7d6b67a40028ce52b4b2b"
   dependencies:
-    debug "2.3.3"
-
-socket.io-client@~2.0.2:
-  version "2.0.3"
-  resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-2.0.3.tgz#6caf4aff9f85b19fd91b6ce13d69adb564f8873b"
-  dependencies:
-    backo2 "1.0.2"
-    base64-arraybuffer "0.1.5"
-    component-bind "1.0.0"
-    component-emitter "1.2.1"
-    debug "~2.6.4"
-    engine.io-client "~3.1.0"
-    has-cors "1.1.0"
-    indexof "0.0.1"
-    object-component "0.0.3"
-    parseqs "0.0.5"
-    parseuri "0.0.5"
-    socket.io-parser "~3.1.1"
-    to-array "0.1.4"
-
-socket.io-parser@~3.1.1:
-  version "3.1.2"
-  resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-3.1.2.tgz#dbc2282151fc4faebbe40aeedc0772eba619f7f2"
-  dependencies:
-    component-emitter "1.2.1"
-    debug "~2.6.4"
-    has-binary2 "~1.0.2"
-    isarray "2.0.1"
-
-socket.io@~2.0.2:
-  version "2.0.3"
-  resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-2.0.3.tgz#4359f06a24933ae6bd087798af78c680eae345e3"
-  dependencies:
-    debug "~2.6.6"
-    engine.io "~3.1.0"
-    object-assign "~4.1.1"
-    socket.io-adapter "~1.1.0"
-    socket.io-client "~2.0.2"
-    socket.io-parser "~3.1.1"
+    hoek "4.x.x"
 
 source-map-support@^0.4.15, source-map-support@^0.4.2:
   version "0.4.15"
@@ -6603,6 +7024,12 @@ source-map-support@^0.4.15, source-map-support@^0.4.2:
   dependencies:
     source-map "^0.5.6"
 
+source-map-support@^0.4.18:
+  version "0.4.18"
+  resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f"
+  dependencies:
+    source-map "^0.5.6"
+
 source-map@0.4.x, source-map@^0.4.2, source-map@^0.4.4:
   version "0.4.4"
   resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b"
@@ -6613,6 +7040,10 @@ source-map@^0.5.0, source-map@^0.5.1, source-map@^0.5.3, source-map@^0.5.6, sour
   version "0.5.6"
   resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412"
 
+source-map@^0.6.1:
+  version "0.6.1"
+  resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
+
 source-map@~0.2.0:
   version "0.2.0"
   resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.2.0.tgz#dab73fbcfc2ba819b4de03bd6f6eaa48164b3f9d"
@@ -6633,12 +7064,22 @@ spdx-license-ids@^1.0.2:
   version "1.2.2"
   resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz#c9df7a3424594ade6bd11900d596696dc06bac57"
 
+spex@~2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/spex/-/spex-2.0.0.tgz#63e1b8655159a32028eb6a237ffb0589e85f3c32"
+
 split@0.3:
   version "0.3.3"
   resolved "https://registry.yarnpkg.com/split/-/split-0.3.3.tgz#cd0eea5e63a211dfff7eb0f091c4133e2d0dd28f"
   dependencies:
     through "2"
 
+split@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/split/-/split-1.0.0.tgz#c4395ce683abcd254bc28fe1dabb6e5c27dcffae"
+  dependencies:
+    through "2"
+
 sprintf-js@1.1.1:
   version "1.1.1"
   resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.1.tgz#36be78320afe5801f6cea3ee78b6e5aab940ea0c"
@@ -6679,20 +7120,12 @@ stdout-stream@^1.4.0:
   dependencies:
     readable-stream "^2.0.1"
 
-stopword@~0.1.6:
-  version "0.1.6"
-  resolved "https://registry.yarnpkg.com/stopword/-/stopword-0.1.6.tgz#435cc3e9d4311aedca2876ed4cae79153cd3d0fb"
-
 stream-combiner@~0.0.4:
   version "0.0.4"
   resolved "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.0.4.tgz#4d5e433c185261dde623ca3f44c586bcf5c4ad14"
   dependencies:
     duplexer "~0.1.1"
 
-stream-shift@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952"
-
 stream-to-array@~2.3.0:
   version "2.3.0"
   resolved "https://registry.yarnpkg.com/stream-to-array/-/stream-to-array-2.3.0.tgz#bbf6b39f5f43ec30bc71babcb37557acecf34353"
@@ -6705,7 +7138,7 @@ stream-to-buffer@^0.1.0:
   dependencies:
     stream-to "~0.2.0"
 
-stream-to-promise@~2.2.0:
+stream-to-promise@2.2.0:
   version "2.2.0"
   resolved "https://registry.yarnpkg.com/stream-to-promise/-/stream-to-promise-2.2.0.tgz#b1edb2e1c8cb11289d1b503c08d3f2aef51e650f"
   dependencies:
@@ -6721,11 +7154,12 @@ streamsearch@0.1.2:
   version "0.1.2"
   resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-0.1.2.tgz#808b9d0e56fc273d809ba57338e929919a1a9f1a"
 
-string-length@^1.0.0, string-length@^1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/string-length/-/string-length-1.0.1.tgz#56970fb1c38558e9e70b728bf3de269ac45adfac"
+string-length@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/string-length/-/string-length-2.0.0.tgz#d40dbb686a3ace960c1cffca562bf2c45f8363ed"
   dependencies:
-    strip-ansi "^3.0.0"
+    astral-regex "^1.0.0"
+    strip-ansi "^4.0.0"
 
 string-width@^1.0.1, string-width@^1.0.2:
   version "1.0.2"
@@ -6750,13 +7184,13 @@ string_decoder@~0.10.x:
   version "0.10.31"
   resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
 
-string_decoder@~1.0.0, string_decoder@~1.0.3:
+string_decoder@~1.0.3:
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab"
   dependencies:
     safe-buffer "~5.1.0"
 
-stringstream@~0.0.4:
+stringstream@~0.0.4, stringstream@~0.0.5:
   version "0.0.5"
   resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878"
 
@@ -6812,19 +7246,29 @@ supports-color@^4.0.0, supports-color@^4.2.0:
   dependencies:
     has-flag "^2.0.0"
 
+supports-color@^4.4.0:
+  version "4.4.0"
+  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.4.0.tgz#883f7ddabc165142b2a61427f3352ded195d1a3e"
+  dependencies:
+    has-flag "^2.0.0"
+
+symbol-observable@^1.0.2, symbol-observable@^1.0.3:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.4.tgz#29bf615d4aa7121bdd898b22d4b3f9bc4e2aa03d"
+
 symbol-tree@^3.2.1:
   version "3.2.2"
   resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.2.tgz#ae27db38f660a7ae2e1c3b7d1bc290819b8519e6"
 
-table-layout@^0.4.1:
-  version "0.4.2"
-  resolved "https://registry.yarnpkg.com/table-layout/-/table-layout-0.4.2.tgz#10e9043c142a1e2d155da7257e478f0ef4981786"
+table-layout@^0.4.0:
+  version "0.4.0"
+  resolved "https://registry.yarnpkg.com/table-layout/-/table-layout-0.4.0.tgz#c70ff0455d9add63b91f7c15a77926295c0e0e7d"
   dependencies:
-    array-back "^2.0.0"
-    deep-extend "~0.5.0"
+    array-back "^1.0.4"
+    deep-extend "~0.4.1"
     lodash.padend "^4.6.1"
-    typical "^2.6.1"
-    wordwrapjs "^3.0.0"
+    typical "^2.6.0"
+    wordwrapjs "^2.0.0"
 
 table@^4.0.1:
   version "4.0.1"
@@ -6837,15 +7281,6 @@ table@^4.0.1:
     slice-ansi "0.0.4"
     string-width "^2.0.0"
 
-tar-fs@^1.13.0:
-  version "1.15.3"
-  resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-1.15.3.tgz#eccf935e941493d8151028e636e51ce4c3ca7f20"
-  dependencies:
-    chownr "^1.0.1"
-    mkdirp "^0.5.1"
-    pump "^1.0.0"
-    tar-stream "^1.1.2"
-
 tar-pack@^3.4.0:
   version "3.4.0"
   resolved "https://registry.yarnpkg.com/tar-pack/-/tar-pack-3.4.0.tgz#23be2d7f671a8339376cbdb0b8fe3fdebf317984"
@@ -6859,24 +7294,7 @@ tar-pack@^3.4.0:
     tar "^2.2.1"
     uid-number "^0.0.6"
 
-tar-stream@^1.1.2:
-  version "1.5.4"
-  resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.5.4.tgz#36549cf04ed1aee9b2a30c0143252238daf94016"
-  dependencies:
-    bl "^1.0.0"
-    end-of-stream "^1.0.0"
-    readable-stream "^2.0.0"
-    xtend "^4.0.0"
-
-tar@^2.0.0, tar@^2.2.1:
-  version "2.2.1"
-  resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1"
-  dependencies:
-    block-stream "*"
-    fstream "^1.0.2"
-    inherits "2"
-
-tar@~4.0.1:
+tar@4.0.1:
   version "4.0.1"
   resolved "https://registry.yarnpkg.com/tar/-/tar-4.0.1.tgz#3f5b2e5289db30c2abe4c960f43d0d9fff96aaf0"
   dependencies:
@@ -6886,15 +7304,31 @@ tar@~4.0.1:
     mkdirp "^0.5.0"
     yallist "^3.0.2"
 
-term-frequency@^0.0.15:
-  version "0.0.15"
-  resolved "https://registry.yarnpkg.com/term-frequency/-/term-frequency-0.0.15.tgz#ff4aeaff2ac31ee1096b5c685852816a5da676e7"
-
-term-vector@^0.1.2:
-  version "0.1.2"
-  resolved "https://registry.yarnpkg.com/term-vector/-/term-vector-0.1.2.tgz#774e7e44aef2274b3b1d8a2441981f99d0f7e0aa"
+tar@^2.0.0, tar@^2.2.1:
+  version "2.2.1"
+  resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1"
   dependencies:
-    lodash.isequal "^4.1.3"
+    block-stream "*"
+    fstream "^1.0.2"
+    inherits "2"
+
+term-size@^1.2.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/term-size/-/term-size-1.2.0.tgz#458b83887f288fc56d6fffbfad262e26638efa69"
+  dependencies:
+    execa "^0.7.0"
+
+terraformer-wkt-parser@^1.1.2:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/terraformer-wkt-parser/-/terraformer-wkt-parser-1.1.2.tgz#336a0c8fc82094a5aff83288f69aedecd369bf0c"
+  dependencies:
+    terraformer "~1.0.5"
+
+terraformer@~1.0.5:
+  version "1.0.8"
+  resolved "https://registry.yarnpkg.com/terraformer/-/terraformer-1.0.8.tgz#51e0ad89746fcf2161dc6f65aa70e42377c8b593"
+  dependencies:
+    "@types/geojson" "^1.0.0"
 
 test-exclude@^4.1.1:
   version "4.1.1"
@@ -6921,25 +7355,21 @@ thirty-two@0.0.2:
   version "0.0.2"
   resolved "https://registry.yarnpkg.com/thirty-two/-/thirty-two-0.0.2.tgz#4253e29d8cb058f0480267c5698c0e4927e54b6a"
 
-throat@^3.0.0:
-  version "3.2.0"
-  resolved "https://registry.yarnpkg.com/throat/-/throat-3.2.0.tgz#50cb0670edbc40237b9e347d7e1f88e4620af836"
+throat@^4.0.0:
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/throat/-/throat-4.1.0.tgz#89037cbc92c56ab18926e6ba4cbb200e15672a6a"
 
-through2@~2.0.3:
+through2@2.0.3:
   version "2.0.3"
   resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be"
   dependencies:
     readable-stream "^2.1.5"
     xtend "~4.0.1"
 
-through@2, "through@>=2.2.7 <3", through@^2.3.6, through@~2.3, through@~2.3.1:
+through@2, through@^2.3.6, through@~2.3, through@~2.3.1:
   version "2.3.8"
   resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
 
-timed-out@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-2.0.0.tgz#f38b0ae81d3747d628001f41dafc652ace671c0a"
-
 timed-out@^4.0.0:
   version "4.0.1"
   resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f"
@@ -6962,10 +7392,6 @@ tmpl@1.0.x:
   version "1.0.4"
   resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1"
 
-to-array@0.1.4:
-  version "0.1.4"
-  resolved "https://registry.yarnpkg.com/to-array/-/to-array-0.1.4.tgz#17e6c11f73dd4f3d74cda7a4ff3238e9ad9bf890"
-
 to-fast-properties@^1.0.1, to-fast-properties@^1.0.3:
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47"
@@ -6974,15 +7400,13 @@ token-stream@0.0.1:
   version "0.0.1"
   resolved "https://registry.yarnpkg.com/token-stream/-/token-stream-0.0.1.tgz#ceeefc717a76c4316f126d0b9dbaa55d7e7df01a"
 
-topo@1.x.x:
-  version "1.1.0"
-  resolved "https://registry.yarnpkg.com/topo/-/topo-1.1.0.tgz#e9d751615d1bb87dc865db182fa1ca0a5ef536d5"
-  dependencies:
-    hoek "2.x.x"
+toposort-class@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/toposort-class/-/toposort-class-1.0.1.tgz#7ffd1f78c8be28c3ba45cd4e1a3f5ee193bd9988"
 
-touch@1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/touch/-/touch-1.0.0.tgz#449cbe2dbae5a8c8038e30d71fa0ff464947c4de"
+touch@^3.1.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/touch/-/touch-3.1.0.tgz#fe365f5f75ec9ed4e56825e0bb76d24ab74af83b"
   dependencies:
     nopt "~1.0.10"
 
@@ -6992,6 +7416,12 @@ tough-cookie@^2.3.2, tough-cookie@~2.3.0:
   dependencies:
     punycode "^1.4.1"
 
+tough-cookie@~2.3.3:
+  version "2.3.3"
+  resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.3.tgz#0b618a5565b6dea90bf3425d04d55edc475a7561"
+  dependencies:
+    punycode "^1.4.1"
+
 tr46@~0.0.3:
   version "0.0.3"
   resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
@@ -7026,7 +7456,7 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0:
   version "0.14.5"
   resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
 
-twemoji-awesome@~1.0.6:
+twemoji-awesome@1.0.6:
   version "1.0.6"
   resolved "https://registry.yarnpkg.com/twemoji-awesome/-/twemoji-awesome-1.0.6.tgz#3167c3abb95753da997291f8f1c53cbac61852a5"
 
@@ -7053,9 +7483,9 @@ typedarray@^0.0.6:
   version "0.0.6"
   resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
 
-typescript@~2.5.2:
-  version "2.5.2"
-  resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.5.2.tgz#038a95f7d9bbb420b1bf35ba31d4c5c1dd3ffe34"
+typescript@2.5.3:
+  version "2.5.3"
+  resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.5.3.tgz#df3dcdc38f3beb800d4bc322646b04a3f6ca7f0d"
 
 typical@^2.6.0, typical@^2.6.1:
   version "2.6.1"
@@ -7069,22 +7499,13 @@ uc.micro@^1.0.1, uc.micro@^1.0.3:
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.3.tgz#7ed50d5e0f9a9fb0a573379259f2a77458d50192"
 
-uglify-es@~3.0.28:
-  version "3.0.28"
-  resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.0.28.tgz#1cdedbbcdb7865223065281ad7b2347629851d4b"
+uglify-es@3.1.3:
+  version "3.1.3"
+  resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.1.3.tgz#a21eeb149cb120a1f8302563689e19496550780b"
   dependencies:
     commander "~2.11.0"
     source-map "~0.5.1"
 
-uglify-js@2.7.5:
-  version "2.7.5"
-  resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.7.5.tgz#4612c0c7baaee2ba7c487de4904ae122079f2ca8"
-  dependencies:
-    async "~0.2.6"
-    source-map "~0.5.1"
-    uglify-to-browserify "~1.0.0"
-    yargs "~3.10.0"
-
 uglify-js@^2.6, uglify-js@^2.6.1:
   version "2.8.29"
   resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd"
@@ -7102,9 +7523,9 @@ uid-number@^0.0.6:
   version "0.0.6"
   resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81"
 
-uid-safe@~2.1.4:
-  version "2.1.4"
-  resolved "https://registry.yarnpkg.com/uid-safe/-/uid-safe-2.1.4.tgz#3ad6f38368c6d4c8c75ec17623fb79aa1d071d81"
+uid-safe@~2.1.5:
+  version "2.1.5"
+  resolved "https://registry.yarnpkg.com/uid-safe/-/uid-safe-2.1.5.tgz#2b3d5c7240e8fc2e58f8aa269e5ee49c0857bd3a"
   dependencies:
     random-bytes "~1.0.0"
 
@@ -7116,21 +7537,27 @@ ultron@1.0.x:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.0.2.tgz#ace116ab557cd197386a4e88f4685378c8b2e4fa"
 
-ultron@~1.1.0:
-  version "1.1.0"
-  resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.0.tgz#b07a2e6a541a815fc6a34ccd4533baec307ca864"
-
 undefsafe@0.0.3:
   version "0.0.3"
   resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-0.0.3.tgz#ecca3a03e56b9af17385baac812ac83b994a962f"
 
+underscore@^1.7.0, underscore@~1.8.3:
+  version "1.8.3"
+  resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.8.3.tgz#4f3fb53b106e6097fcf9cb4109f2a5e9bdfa5022"
+
 underscore@~1.5.1:
   version "1.5.2"
   resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.5.2.tgz#1335c5e4f5e6d33bbb4b006ba8c86a00f556de08"
 
-underscore@~1.8.3:
-  version "1.8.3"
-  resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.8.3.tgz#4f3fb53b106e6097fcf9cb4109f2a5e9bdfa5022"
+uniq@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff"
+
+unique-string@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-1.0.0.tgz#9e1057cca851abb93398f8b33ae187b99caec11a"
+  dependencies:
+    crypto-random-string "^1.0.0"
 
 universalify@^0.1.0:
   version "0.1.1"
@@ -7140,21 +7567,22 @@ unpipe@1.0.0, unpipe@~1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
 
-unzip-response@^1.0.0:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-1.0.2.tgz#b984f0877fc0a89c2c773cc1ef7b5b232b5b06fe"
+unzip-response@^2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-2.0.1.tgz#d2f0f737d16b0615e72a6935ed04214572d56f97"
 
-update-notifier@0.5.0:
-  version "0.5.0"
-  resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-0.5.0.tgz#07b5dc2066b3627ab3b4f530130f7eddda07a4cc"
+update-notifier@^2.2.0:
+  version "2.2.0"
+  resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-2.2.0.tgz#1b5837cf90c0736d88627732b661c138f86de72f"
   dependencies:
+    boxen "^1.0.0"
     chalk "^1.0.0"
-    configstore "^1.0.0"
+    configstore "^3.0.0"
+    import-lazy "^2.1.0"
     is-npm "^1.0.0"
-    latest-version "^1.0.0"
-    repeating "^1.1.2"
+    latest-version "^3.0.0"
     semver-diff "^2.0.0"
-    string-length "^1.0.0"
+    xdg-basedir "^3.0.0"
 
 url-parse-lax@^1.0.0:
   version "1.0.0"
@@ -7201,18 +7629,18 @@ utils-merge@1.0.0, utils-merge@1.x.x:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.0.tgz#0294fb922bb9375153541c4f7096231f287c8af8"
 
-uuid@^2.0.1, uuid@^2.0.2:
+utils-merge@1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
+
+uuid@^2.0.2:
   version "2.0.3"
   resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.3.tgz#67e2e863797215530dff318e5bf9dcebfd47b21a"
 
-uuid@^3.0.0, uuid@^3.0.1:
+uuid@^3.0.0, uuid@^3.0.1, uuid@^3.1.0:
   version "3.1.0"
   resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.1.0.tgz#3dd3d3e790abc24d7b0d3a034ffababe28ebbc04"
 
-uws@~0.14.4:
-  version "0.14.5"
-  resolved "https://registry.yarnpkg.com/uws/-/uws-0.14.5.tgz#67aaf33c46b2a587a5f6666d00f7691328f149dc"
-
 v8flags@^2.1.1:
   version "2.1.1"
   resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-2.1.1.tgz#aab1a1fa30d45f88dd321148875ac02c0b55e5b4"
@@ -7226,7 +7654,7 @@ validate-npm-package-license@^3.0.1:
     spdx-correct "~1.0.0"
     spdx-expression-parse "~1.0.0"
 
-validator-as-promised@~1.0.2:
+validator-as-promised@1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/validator-as-promised/-/validator-as-promised-1.0.2.tgz#2ea062b2fa703b7dfd71cb34a2f12fe0894f41ce"
   dependencies:
@@ -7234,11 +7662,15 @@ validator-as-promised@~1.0.2:
     lodash "^4.14.0"
     validator "^5.5.0"
 
+validator@9.0.0:
+  version "9.0.0"
+  resolved "https://registry.yarnpkg.com/validator/-/validator-9.0.0.tgz#6c1ef955e007af704adea86ae8a76da84a6c172e"
+
 validator@^5.5.0:
   version "5.7.0"
   resolved "https://registry.yarnpkg.com/validator/-/validator-5.7.0.tgz#7a87a58146b695ac486071141c0c49d67da05e5c"
 
-validator@~8.1.0:
+validator@^8.0.0:
   version "8.1.0"
   resolved "https://registry.yarnpkg.com/validator/-/validator-8.1.0.tgz#89cf6b512ff71eba886afd8d10d47f8dc800eac0"
 
@@ -7250,15 +7682,19 @@ vary@~1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/vary/-/vary-1.0.1.tgz#99e4981566a286118dfb2b817357df7993376d10"
 
+vary@~1.1.2:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
+
 vasync@^1.6.4:
   version "1.6.4"
   resolved "https://registry.yarnpkg.com/vasync/-/vasync-1.6.4.tgz#dfe93616ad0e7ae801b332a9d88bfc5cdc8e1d1f"
   dependencies:
     verror "1.6.0"
 
-vee-validate@~2.0.0-rc.14:
-  version "2.0.0-rc.14"
-  resolved "https://registry.yarnpkg.com/vee-validate/-/vee-validate-2.0.0-rc.14.tgz#ecbd3ddff33fa6a42ebb4a468c343e1eb5d2b38f"
+vee-validate@2.0.0-rc.18:
+  version "2.0.0-rc.18"
+  resolved "https://registry.yarnpkg.com/vee-validate/-/vee-validate-2.0.0-rc.18.tgz#30857abeb2ba87e52d3e66c09b35a78e66419527"
 
 verror@1.3.6:
   version "1.3.6"
@@ -7290,40 +7726,61 @@ void-elements@^2.0.1:
   version "2.0.1"
   resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec"
 
-vue-clipboards@~1.1.0:
+vue-clipboards@1.1.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/vue-clipboards/-/vue-clipboards-1.1.0.tgz#708d95b64e64f83e565f7fc464e7213fb6ef2d8a"
   dependencies:
     clipboard "^1.7.1"
 
-vue-lodash@~1.0.3:
-  version "1.0.3"
-  resolved "https://registry.yarnpkg.com/vue-lodash/-/vue-lodash-1.0.3.tgz#777ef3e190a4cdde0d211a614e52a0b38659c13f"
+vue-hot-reload-api@2.1.1:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/vue-hot-reload-api/-/vue-hot-reload-api-2.1.1.tgz#1ba6712166182fd651753804b9d8d8d02d855579"
 
-vue-resource@~1.3.4:
+vue-lodash@1.0.4:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/vue-lodash/-/vue-lodash-1.0.4.tgz#99f4f2f5832ce0168c4d45618789288a638562cd"
+
+vue-material@^0.7.5:
+  version "0.7.5"
+  resolved "https://registry.yarnpkg.com/vue-material/-/vue-material-0.7.5.tgz#045517403c1338aceabd73030f3dd6b5c744fe55"
+
+vue-resource@1.3.4:
   version "1.3.4"
   resolved "https://registry.yarnpkg.com/vue-resource/-/vue-resource-1.3.4.tgz#9fc0bdf6a2f5cab430129fc99d347b3deae7b099"
   dependencies:
     got "^7.0.0"
 
-vue-template-compiler@~2.4.2:
-  version "2.4.2"
-  resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.4.2.tgz#5a45d843f148b098f6c1d1e35ac20c4956d30ad1"
+vue-simple-breakpoints@1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/vue-simple-breakpoints/-/vue-simple-breakpoints-1.0.2.tgz#87aae092f853c7f26e6b99950385f108ccf399c9"
+  dependencies:
+    simple-breakpoints "^1.1.1"
+
+vue-template-compiler@2.4.4:
+  version "2.4.4"
+  resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.4.4.tgz#2cde3b704124985c27d50b5387c9691ba515fb57"
   dependencies:
     de-indent "^1.0.2"
     he "^1.1.0"
 
-vue-template-es2015-compiler@~1.5.3:
+vue-template-es2015-compiler@1.5.3:
   version "1.5.3"
   resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.5.3.tgz#22787de4e37ebd9339b74223bc467d1adee30545"
 
-vue@~2.4.2:
-  version "2.4.2"
-  resolved "https://registry.yarnpkg.com/vue/-/vue-2.4.2.tgz#a9855261f191c978cc0dc1150531b8d08149b58c"
+vue@2.4.4:
+  version "2.4.4"
+  resolved "https://registry.yarnpkg.com/vue/-/vue-2.4.4.tgz#ea9550b96a71465fd2b8b17b61673b3561861789"
 
-vuex@~2.4.0:
-  version "2.4.0"
-  resolved "https://registry.yarnpkg.com/vuex/-/vuex-2.4.0.tgz#e1d0430646282b40007fdd06ec6ae88a9f5a1e14"
+vuex-persistedstate@2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/vuex-persistedstate/-/vuex-persistedstate-2.0.0.tgz#b84f530da4679bdf694c5ddf65c23033aa79b1bb"
+  dependencies:
+    lodash.merge "^4.6.0"
+    object-path "^0.11.2"
+
+vuex@2.4.1:
+  version "2.4.1"
+  resolved "https://registry.yarnpkg.com/vuex/-/vuex-2.4.1.tgz#7890b650ba8565b70937b4e7670577082dfe8bc1"
 
 vxx@^1.2.0:
   version "1.2.2"
@@ -7376,7 +7833,7 @@ whatwg-encoding@^1.0.1:
   dependencies:
     iconv-lite "0.4.13"
 
-whatwg-fetch@^2.0.3:
+whatwg-fetch@^2.0.0, whatwg-fetch@^2.0.3:
   version "2.0.3"
   resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz#9c84ec2dcf68187ff00bc64e1274b442176e1c84"
 
@@ -7407,13 +7864,19 @@ wide-align@^1.1.0:
   dependencies:
     string-width "^1.0.2"
 
+widest-line@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-1.0.0.tgz#0c09c85c2a94683d0d7eaf8ee097d564bf0e105c"
+  dependencies:
+    string-width "^1.0.1"
+
 window-size@0.1.0:
   version "0.1.0"
   resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d"
 
-winston@~2.3.1:
-  version "2.3.1"
-  resolved "https://registry.yarnpkg.com/winston/-/winston-2.3.1.tgz#0b48420d978c01804cf0230b648861598225a119"
+winston@2.4.0:
+  version "2.4.0"
+  resolved "https://registry.yarnpkg.com/winston/-/winston-2.4.0.tgz#808050b93d52661ed9fb6c26b3f0c826708b0aee"
   dependencies:
     async "~1.0.0"
     colors "1.0.x"
@@ -7429,6 +7892,12 @@ with@^5.0.0:
     acorn "^3.1.0"
     acorn-globals "^3.0.0"
 
+wkx@^0.4.1:
+  version "0.4.1"
+  resolved "https://registry.yarnpkg.com/wkx/-/wkx-0.4.1.tgz#2fc171b5e9cb55c6256fef4bde1f21be413befee"
+  dependencies:
+    "@types/node" "^6.0.48"
+
 wordwrap@0.0.2:
   version "0.0.2"
   resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f"
@@ -7441,12 +7910,14 @@ wordwrap@~1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb"
 
-wordwrapjs@^3.0.0:
-  version "3.0.0"
-  resolved "https://registry.yarnpkg.com/wordwrapjs/-/wordwrapjs-3.0.0.tgz#c94c372894cadc6feb1a66bff64e1d9af92c5d1e"
+wordwrapjs@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/wordwrapjs/-/wordwrapjs-2.0.0.tgz#ab55f695e6118da93858fdd70c053d1c5e01ac20"
   dependencies:
+    array-back "^1.0.3"
+    feature-detect-es6 "^1.3.1"
     reduce-flatten "^1.0.1"
-    typical "^2.6.1"
+    typical "^2.6.0"
 
 worker-farm@^1.3.1:
   version "1.4.1"
@@ -7466,13 +7937,13 @@ wrappy@1:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
 
-write-file-atomic@^1.1.2:
-  version "1.3.4"
-  resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-1.3.4.tgz#f807a4f0b1d9e913ae7a48112e6cc3af1991b45f"
+write-file-atomic@^2.0.0, write-file-atomic@^2.1.0:
+  version "2.3.0"
+  resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.3.0.tgz#1ff61575c2e2a4e8e510d6fa4e243cce183999ab"
   dependencies:
     graceful-fs "^4.1.11"
     imurmurhash "^0.1.4"
-    slide "^1.1.5"
+    signal-exit "^3.0.2"
 
 write@^0.2.1:
   version "0.2.1"
@@ -7487,18 +7958,9 @@ ws@^1.1.1:
     options ">=0.0.5"
     ultron "1.0.x"
 
-ws@~2.3.1:
-  version "2.3.1"
-  resolved "https://registry.yarnpkg.com/ws/-/ws-2.3.1.tgz#6b94b3e447cb6a363f785eaf94af6359e8e81c80"
-  dependencies:
-    safe-buffer "~5.0.1"
-    ultron "~1.1.0"
-
-xdg-basedir@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-2.0.0.tgz#edbc903cc385fc04523d966a335504b5504d1bd2"
-  dependencies:
-    os-homedir "^1.0.0"
+xdg-basedir@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-3.0.0.tgz#496b2cc109eca8dbacfe2dc72b603c17c5870ad4"
 
 xhr@^2.0.1:
   version "2.4.0"
@@ -7524,21 +7986,13 @@ xml2js@^0.4.5:
     sax ">=0.6.0"
     xmlbuilder "^4.1.0"
 
-xml@^1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/xml/-/xml-1.0.1.tgz#78ba72020029c5bc87b8a81a3cfcd74b4a2fc1e5"
-
 xmlbuilder@^4.1.0:
   version "4.2.1"
   resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-4.2.1.tgz#aa58a3041a066f90eaa16c2f5389ff19f3f461a5"
   dependencies:
     lodash "^4.0.0"
 
-xmlhttprequest-ssl@1.5.3:
-  version "1.5.3"
-  resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.3.tgz#185a888c04eca46c3e4070d99f7b49de3528992d"
-
-xtend@4.0.1, xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.0, xtend@~4.0.1:
+xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.1:
   version "4.0.1"
   resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"
 
@@ -7573,7 +8027,25 @@ yargs-parser@^7.0.0:
   dependencies:
     camelcase "^4.1.0"
 
-yargs@^7.0.0, yargs@^7.0.2:
+yargs@9.0.1:
+  version "9.0.1"
+  resolved "https://registry.yarnpkg.com/yargs/-/yargs-9.0.1.tgz#52acc23feecac34042078ee78c0c007f5085db4c"
+  dependencies:
+    camelcase "^4.1.0"
+    cliui "^3.2.0"
+    decamelize "^1.1.1"
+    get-caller-file "^1.0.1"
+    os-locale "^2.0.0"
+    read-pkg-up "^2.0.0"
+    require-directory "^2.1.1"
+    require-main-filename "^1.0.1"
+    set-blocking "^2.0.0"
+    string-width "^2.0.0"
+    which-module "^2.0.0"
+    y18n "^3.2.1"
+    yargs-parser "^7.0.0"
+
+yargs@^7.0.0:
   version "7.1.0"
   resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.0.tgz#6ba318eb16961727f5d284f8ea003e8d6154d0c8"
   dependencies:
@@ -7591,18 +8063,9 @@ yargs@^7.0.0, yargs@^7.0.2:
     y18n "^3.2.1"
     yargs-parser "^5.0.0"
 
-yargs@~3.10.0:
-  version "3.10.0"
-  resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1"
-  dependencies:
-    camelcase "^1.0.2"
-    cliui "^2.1.0"
-    decamelize "^1.0.0"
-    window-size "0.1.0"
-
-yargs@~8.0.1:
-  version "8.0.2"
-  resolved "https://registry.yarnpkg.com/yargs/-/yargs-8.0.2.tgz#6299a9055b1cefc969ff7e79c1d918dceb22c360"
+yargs@^9.0.0:
+  version "9.0.0"
+  resolved "https://registry.yarnpkg.com/yargs/-/yargs-9.0.0.tgz#efe5b1ad3f94bdc20423411b90628eeec0b25f3c"
   dependencies:
     camelcase "^4.1.0"
     cliui "^3.2.0"
@@ -7618,9 +8081,22 @@ yargs@~8.0.1:
     y18n "^3.2.1"
     yargs-parser "^7.0.0"
 
-yeast@0.1.2:
-  version "0.1.2"
-  resolved "https://registry.yarnpkg.com/yeast/-/yeast-0.1.2.tgz#008e06d8094320c372dbc2f8ed76a0ca6c8ac419"
+yargs@~3.10.0:
+  version "3.10.0"
+  resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1"
+  dependencies:
+    camelcase "^1.0.2"
+    cliui "^2.1.0"
+    decamelize "^1.0.0"
+    window-size "0.1.0"
+
+zen-observable-ts@^0.4.4:
+  version "0.4.4"
+  resolved "https://registry.yarnpkg.com/zen-observable-ts/-/zen-observable-ts-0.4.4.tgz#c244c71eaebef79a985ccf9895bc90307a6e9712"
+
+zen-observable-ts@^0.5.0:
+  version "0.5.0"
+  resolved "https://registry.yarnpkg.com/zen-observable-ts/-/zen-observable-ts-0.5.0.tgz#c5021e7ac486fc281f6126d574673cfb6daf0069"
 
 zone.js@0.7.6:
   version "0.7.6"