diff --git a/.gitignore b/.gitignore
index 0f0a4c49b11320099d4b401e0e48058dbc37dea2..7cd721e4a029560c0c3244339da050941539fadb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -57,8 +57,7 @@ typings/
 # dotenv environment variables file
 .env
 
-# webpack bundle
-public/*.bundle.js*
-public/*.html
+# Ignore public folder with webpack build output
+public/
 
 .DS_Store
diff --git a/README.md b/README.md
index 9a6a277406a70334e37cc627438f5817bf3f4ea6..c6341e6b62e4efb6093de487f229c64d2cfab76f 100644
--- a/README.md
+++ b/README.md
@@ -40,5 +40,5 @@ Ex.
 Will become:
 
 ```html
-<img src="https://cdn.mysite.com/assets/asseturl.png?c=1512428142413"/>
+<img src="https://cdn.mysite.com/assets/asseturl.png?crc=f37a775"/>
 ```
diff --git a/config.js b/config.js
new file mode 100644
index 0000000000000000000000000000000000000000..88ac5cdc84d941cd161fa4067e65c62521a50d7c
--- /dev/null
+++ b/config.js
@@ -0,0 +1,16 @@
+module.exports = {
+  // This origin trial token is used to enable WebVR and Gamepad Extensions on Chrome 62+
+  // You can find more information about getting your own origin trial token here: https://github.com/GoogleChrome/OriginTrials/blob/gh-pages/developer-guide.md
+  originTrialToken:
+    "AvIMoF4hyRZQVfSfksoqP+7qzwa4FSBzHRHvUyzC8rMATJVRbcOiLewBxbXtJVyV3N62gsZv7PoSNtDqqtjzYAcAAABkeyJvcmlnaW4iOiJodHRwczovL3JldGljdWx1bS5pbzo0NDMiLCJmZWF0dXJlIjoiV2ViVlIxLjFNNjIiLCJleHBpcnkiOjE1MTYxNDYyMDQsImlzU3ViZG9tYWluIjp0cnVlfQ==",
+  originTrialExpires: "2018-01-16",
+
+  // These variables are availible on the window.CONFIG object
+  // The exported object must be a valid argument to JSON.stringify()
+  global: {
+    janus_server_url:
+      process.env.JANUS_SERVER || "wss://dev-janus.reticulum.io",
+    public_rooms: [1, 2, 3, 4, 5],
+    default_room: 1
+  }
+};
diff --git a/package.json b/package.json
index ddad5b3e6bededd8ffb68262122f8da9763e3f9c..fe6d10be9930adb78e5b7e6f34608ca825252b48 100644
--- a/package.json
+++ b/package.json
@@ -6,7 +6,7 @@
   "scripts": {
     "start": "npm run dev",
     "dev": "webpack-dev-server --https --host 0.0.0.0 --useLocalIp --open --config webpack.dev.js",
-    "build": "NODE_ENV='production' webpack --config webpack.prod.js",
+    "build": "cross-env NODE_ENV='production' webpack --config webpack.prod.js",
     "prettier": "prettier --write src/**/*.js"
   },
   "dependencies": {
@@ -14,13 +14,16 @@
     "aframe-extras": "^3.12.4",
     "aframe-input-mapping-component": "https://github.com/fernandojsg/aframe-input-mapping-component#6ebc38f",
     "aframe-teleport-controls": "https://github.com/netpro2k/aframe-teleport-controls#feature/teleport-origin",
+    "extract-text-webpack-plugin": "^3.0.2",
+    "material-design-lite": "^1.3.0",
     "minijanus": "^0.1.6",
     "naf-janus-adapter": "https://github.com/mozilla/naf-janus-adapter#fix/multiple-get-mediastreams",
     "networked-aframe": "https://github.com/netpro2k/networked-aframe#bugfix/chrome/audio",
     "nipplejs": "^0.6.7",
     "query-string": "^5.0.1",
     "react": "^16.1.1",
-    "react-dom": "^16.1.1"
+    "react-dom": "^16.1.1",
+    "webrtc-adapter": "^6.0.2"
   },
   "resolutions": {
     "webpack-sources": "1.0.1"
@@ -28,20 +31,28 @@
   "devDependencies": {
     "babel-core": "^6.26.0",
     "babel-loader": "^7.1.2",
-    "babel-minify-webpack-plugin": "^0.2.0",
     "babel-preset-env": "^1.6.1",
     "babel-preset-react": "^6.24.1",
     "chokidar": "^1.7.0",
+    "clean-webpack-plugin": "^0.1.17",
+    "copy-webpack-plugin": "^4.2.3",
+    "crc": "^3.5.0",
+    "cross-env": "^5.1.1",
     "css-loader": "^0.28.7",
     "eslint": "^4.10.0",
     "eslint-config-prettier": "^2.6.0",
     "eslint-plugin-prettier": "^2.3.1",
+    "file-loader": "^1.1.5",
     "fs-extra": "^4.0.2",
+    "glob": "^7.1.2",
     "handlebars": "^4.0.11",
+    "optimize-css-assets-webpack-plugin": "^3.2.0",
     "prettier": "^1.7.0",
     "style-loader": "^0.19.0",
+    "uglifyjs-webpack-plugin": "^1.1.2",
     "webpack": "^3.6.0",
     "webpack-dev-server": "^2.9.3",
-    "webpack-merge": "^4.1.0"
+    "webpack-merge": "^4.1.0",
+    "write-file-webpack-plugin": "^4.2.0"
   }
 }
diff --git a/public/assets/avatars/Bot_Body_Mesh.glb b/src/assets/avatars/Bot_Body_Mesh.glb
similarity index 100%
rename from public/assets/avatars/Bot_Body_Mesh.glb
rename to src/assets/avatars/Bot_Body_Mesh.glb
diff --git a/public/assets/avatars/Bot_Head_Mesh.glb b/src/assets/avatars/Bot_Head_Mesh.glb
similarity index 100%
rename from public/assets/avatars/Bot_Head_Mesh.glb
rename to src/assets/avatars/Bot_Head_Mesh.glb
diff --git a/public/assets/avatars/Bot_LeftHand_Mesh.glb b/src/assets/avatars/Bot_LeftHand_Mesh.glb
similarity index 100%
rename from public/assets/avatars/Bot_LeftHand_Mesh.glb
rename to src/assets/avatars/Bot_LeftHand_Mesh.glb
diff --git a/public/assets/avatars/Bot_RightHand_Mesh.glb b/src/assets/avatars/Bot_RightHand_Mesh.glb
similarity index 100%
rename from public/assets/avatars/Bot_RightHand_Mesh.glb
rename to src/assets/avatars/Bot_RightHand_Mesh.glb
diff --git a/public/assets/avatars/dodec/AvatarHand_L/AvatarDodeca_Texture.png b/src/assets/avatars/dodec/AvatarHand_L/AvatarDodeca_Texture.png
similarity index 100%
rename from public/assets/avatars/dodec/AvatarHand_L/AvatarDodeca_Texture.png
rename to src/assets/avatars/dodec/AvatarHand_L/AvatarDodeca_Texture.png
diff --git a/public/assets/avatars/dodec/AvatarHand_L/Avatar_HandL.bin b/src/assets/avatars/dodec/AvatarHand_L/Avatar_HandL.bin
similarity index 100%
rename from public/assets/avatars/dodec/AvatarHand_L/Avatar_HandL.bin
rename to src/assets/avatars/dodec/AvatarHand_L/Avatar_HandL.bin
diff --git a/public/assets/avatars/dodec/AvatarHand_L/Avatar_HandL.gltf b/src/assets/avatars/dodec/AvatarHand_L/Avatar_HandL.gltf
similarity index 100%
rename from public/assets/avatars/dodec/AvatarHand_L/Avatar_HandL.gltf
rename to src/assets/avatars/dodec/AvatarHand_L/Avatar_HandL.gltf
diff --git a/public/assets/avatars/dodec/AvatarHand_R/AvatarDodeca_Texture.png b/src/assets/avatars/dodec/AvatarHand_R/AvatarDodeca_Texture.png
similarity index 100%
rename from public/assets/avatars/dodec/AvatarHand_R/AvatarDodeca_Texture.png
rename to src/assets/avatars/dodec/AvatarHand_R/AvatarDodeca_Texture.png
diff --git a/public/assets/avatars/dodec/AvatarHand_R/Avatar_HandR.bin b/src/assets/avatars/dodec/AvatarHand_R/Avatar_HandR.bin
similarity index 100%
rename from public/assets/avatars/dodec/AvatarHand_R/Avatar_HandR.bin
rename to src/assets/avatars/dodec/AvatarHand_R/Avatar_HandR.bin
diff --git a/public/assets/avatars/dodec/AvatarHand_R/Avatar_HandR.gltf b/src/assets/avatars/dodec/AvatarHand_R/Avatar_HandR.gltf
similarity index 100%
rename from public/assets/avatars/dodec/AvatarHand_R/Avatar_HandR.gltf
rename to src/assets/avatars/dodec/AvatarHand_R/Avatar_HandR.gltf
diff --git a/public/assets/avatars/dodec/DodecAvatarGLTF/AvatarDodeca_Texture.png b/src/assets/avatars/dodec/DodecAvatarGLTF/AvatarDodeca_Texture.png
similarity index 100%
rename from public/assets/avatars/dodec/DodecAvatarGLTF/AvatarDodeca_Texture.png
rename to src/assets/avatars/dodec/DodecAvatarGLTF/AvatarDodeca_Texture.png
diff --git a/public/assets/avatars/dodec/DodecAvatarGLTF/DodecAvatar_Head.bin b/src/assets/avatars/dodec/DodecAvatarGLTF/DodecAvatar_Head.bin
similarity index 100%
rename from public/assets/avatars/dodec/DodecAvatarGLTF/DodecAvatar_Head.bin
rename to src/assets/avatars/dodec/DodecAvatarGLTF/DodecAvatar_Head.bin
diff --git a/public/assets/avatars/dodec/DodecAvatarGLTF/DodecAvatar_Head.gltf b/src/assets/avatars/dodec/DodecAvatarGLTF/DodecAvatar_Head.gltf
similarity index 100%
rename from public/assets/avatars/dodec/DodecAvatarGLTF/DodecAvatar_Head.gltf
rename to src/assets/avatars/dodec/DodecAvatarGLTF/DodecAvatar_Head.gltf
diff --git a/src/assets/background.jpg b/src/assets/background.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..81d79011ef693a8ed43a22d56fa8774d8ad4ad45
Binary files /dev/null and b/src/assets/background.jpg differ
diff --git a/public/assets/environments/CliffVista_mesh.glb b/src/assets/environments/CliffVista_mesh.glb
similarity index 100%
rename from public/assets/environments/CliffVista_mesh.glb
rename to src/assets/environments/CliffVista_mesh.glb
diff --git a/public/assets/environments/FloorNav_mesh.glb b/src/assets/environments/FloorNav_mesh.glb
similarity index 100%
rename from public/assets/environments/FloorNav_mesh.glb
rename to src/assets/environments/FloorNav_mesh.glb
diff --git a/public/assets/environments/MeetingSpace1_mesh.glb b/src/assets/environments/MeetingSpace1_mesh.glb
similarity index 100%
rename from public/assets/environments/MeetingSpace1_mesh.glb
rename to src/assets/environments/MeetingSpace1_mesh.glb
diff --git a/public/assets/environments/OutdoorFacade_mesh.glb b/src/assets/environments/OutdoorFacade_mesh.glb
similarity index 100%
rename from public/assets/environments/OutdoorFacade_mesh.glb
rename to src/assets/environments/OutdoorFacade_mesh.glb
diff --git a/public/assets/environments/RockIslandTest/LowPolyGradients.png b/src/assets/environments/RockIslandTest/LowPolyGradients.png
similarity index 100%
rename from public/assets/environments/RockIslandTest/LowPolyGradients.png
rename to src/assets/environments/RockIslandTest/LowPolyGradients.png
diff --git a/public/assets/environments/RockIslandTest/RockIsland.bin b/src/assets/environments/RockIslandTest/RockIsland.bin
similarity index 100%
rename from public/assets/environments/RockIslandTest/RockIsland.bin
rename to src/assets/environments/RockIslandTest/RockIsland.bin
diff --git a/public/assets/environments/RockIslandTest/RockIsland.gltf b/src/assets/environments/RockIslandTest/RockIsland.gltf
similarity index 100%
rename from public/assets/environments/RockIslandTest/RockIsland.gltf
rename to src/assets/environments/RockIslandTest/RockIsland.gltf
diff --git a/public/assets/grid.png b/src/assets/grid.png
similarity index 100%
rename from public/assets/grid.png
rename to src/assets/grid.png
diff --git a/public/assets/hud/watch.bin b/src/assets/hud/watch.bin
similarity index 100%
rename from public/assets/hud/watch.bin
rename to src/assets/hud/watch.bin
diff --git a/public/assets/hud/watch.gltf b/src/assets/hud/watch.gltf
similarity index 100%
rename from public/assets/hud/watch.gltf
rename to src/assets/hud/watch.gltf
diff --git a/public/assets/loading.gif b/src/assets/loading.gif
similarity index 100%
rename from public/assets/loading.gif
rename to src/assets/loading.gif
diff --git a/src/components/cached-gltf-model.js b/src/components/cached-gltf-model.js
index c50b6788228ddb2a79beaa9202ac50be6a75adcf..f52a2bba0a00a4a273aa450534fad38c8f89e599 100644
--- a/src/components/cached-gltf-model.js
+++ b/src/components/cached-gltf-model.js
@@ -1,5 +1,3 @@
-import "../vendor/GLTFLoader";
-
 const GLTFCache = {};
 
 // From https://gist.github.com/cdata/f2d7a6ccdec071839bc1954c32595e87
diff --git a/src/components/character-controller.js b/src/components/character-controller.js
index 175c66384d924f3eaea784d204b280e79be466eb..f20c758d04fec67ca3b8a20070965b4c8714073b 100644
--- a/src/components/character-controller.js
+++ b/src/components/character-controller.js
@@ -1,4 +1,3 @@
-import AFRAME from "aframe";
 const CLAMP_VELOCITY = 0.01;
 const MAX_DELTA = 0.2;
 
diff --git a/src/config.js b/src/config.js
deleted file mode 100644
index 194137a54fcc529032ea94d3c62a7581f6d4fd84..0000000000000000000000000000000000000000
--- a/src/config.js
+++ /dev/null
@@ -1,5 +0,0 @@
-export default {
-  janus_server_url: "wss://dev-janus.reticulum.io",
-  public_rooms: [1, 2, 3, 4, 5],
-  default_room: 1
-};
diff --git a/src/lobby.css b/src/lobby.css
index a995a61eac6cd2eb7f693b9869296565e475013b..a9af59af9df3e6808ce1113af22af61d19e1d8bc 100644
--- a/src/lobby.css
+++ b/src/lobby.css
@@ -5,13 +5,13 @@
 body {
   margin: 0;
   padding: 0;
-  background: black url(https://cdn.glitch.com/52bf1803-98d8-450b-83f4-f74024eb22e5%2Fwallpaper_HD_firefox.jpg?1510615261238) no-repeat left center;
+  background: black url(./assets/background.jpg) no-repeat left center;
   background-size: auto 100%;
 }
 
 .overlay {
   display: flex;
-  background: rgba(0,0,0,0.4);
+  background: rgba(0, 0, 0, 0.4);
   width: 100vw;
   height: 100vh;
   align-items: center;
@@ -24,35 +24,35 @@ body {
 }
 
 .scroll {
-    flex: 1;
-    overflow-y: auto;
+  flex: 1;
+  overflow-y: auto;
 }
 
 .mdl-list {
-    margin: 0;
+  margin: 0;
 }
 
 .room-item {
-    padding: 0;
+  padding: 0;
 }
 
 .room-item a {
-    width: 100%;
-    height: 100%;
-    padding: 16px;
-    color: inherit;
-    text-decoration: none;
+  width: 100%;
+  height: 100%;
+  padding: 16px;
+  color: inherit;
+  text-decoration: none;
 }
 
 .room-item a:hover {
-    background: #eaeaea;
+  background: #eaeaea;
 }
 
-@media only screen and (max-width : 320px) {
-    .overlay {
-        padding: 0;
-    }
-    .panel {
-        width: 100%;
-    }
+@media only screen and (max-width: 320px) {
+  .overlay {
+    padding: 0;
+  }
+  .panel {
+    width: 100%;
+  }
 }
diff --git a/src/lobby.js b/src/lobby.js
index 61b3e35e814aa31763335a3a75076b5c534a1e4e..3ab122f79af38bafaf28a1d50d2a20680ec567f0 100644
--- a/src/lobby.js
+++ b/src/lobby.js
@@ -2,8 +2,8 @@ import React from "react";
 import ReactDOM from "react-dom";
 import mj from "minijanus";
 
-import Config from "./config";
-
+import "material-design-lite";
+import "material-design-lite/material.css";
 import "./lobby.css";
 
 class Lobby extends React.Component {
@@ -17,7 +17,7 @@ class Lobby extends React.Component {
   }
 
   componentDidMount() {
-    this.ws = new WebSocket(Config.janus_server_url, "janus-protocol");
+    this.ws = new WebSocket(window.CONFIG.janus_server_url, "janus-protocol");
     this.session = new mj.JanusSession(this.ws.send.bind(this.ws));
     this.ws.addEventListener("open", this.onWebsocketOpen);
     this.ws.addEventListener("message", this.onWebsocketMessage);
@@ -46,12 +46,14 @@ class Lobby extends React.Component {
   }
 
   fetchRooms() {
-    return this.handle
-      .sendMessage({ kind: "listusers" })
-      .then(signal => {
-        const usersByRoom = signal.plugindata.data.response.users;
-        return Config.public_rooms.map(id => ({id, limit: 12, users: usersByRoom[id] || []}));
-      });
+    return this.handle.sendMessage({ kind: "listusers" }).then(signal => {
+      const usersByRoom = signal.plugindata.data.response.users;
+      return window.CONFIG.public_rooms.map(id => ({
+        id,
+        limit: 12,
+        users: usersByRoom[id] || []
+      }));
+    });
   }
 
   onWebsocketMessage(event) {
@@ -85,7 +87,7 @@ const RoomListItem = ({ room }) => {
 };
 
 const RoomList = ({ rooms }) => {
-  const publicRooms = Config.public_rooms.length + 1;
+  const publicRooms = window.CONFIG.public_rooms.length + 1;
   const roomId =
     publicRooms +
     Math.floor(Math.random() * (Number.MAX_SAFE_INTEGER - publicRooms));
diff --git a/src/index.js b/src/room.js
similarity index 95%
rename from src/index.js
rename to src/room.js
index 0d4e04c91a232b5122efe6744cd080a6563b7f28..6b5d8e9f59a88b060ce6ffe5975006829e671c85 100644
--- a/src/index.js
+++ b/src/room.js
@@ -29,7 +29,6 @@ import "./systems/personal-space-bubble";
 import registerNetworkScheams from "./network-schemas";
 import registerInputMappings from "./input-mappings";
 import { promptForName, getCookie, parseJwt } from "./utils";
-import Config from "./config";
 
 registerNetworkScheams();
 registerInputMappings();
@@ -65,8 +64,8 @@ window.App = {
       room:
         qs.room && !isNaN(parseInt(qs.room))
           ? parseInt(qs.room)
-          : Config.default_room,
-      serverURL: Config.janus_server_url
+          : window.CONFIG.default_room,
+      serverURL: window.CONFIG.janus_server_url
     });
 
     if (!qs.stats || !/off|false|0/.test(qs.stats)) {
@@ -80,15 +79,15 @@ window.App = {
 
     let username;
     const jwt = getCookie("jwt");
-    if (jwt) { //grab name from jwt
+    if (jwt) {
+      //grab name from jwt
       const data = parseJwt(jwt);
       username = data.typ.name;
     }
 
     if (qs.name) {
-      username = qs.name; //always override with name from querystring if available 
-    } 
-    else {
+      username = qs.name; //always override with name from querystring if available
+    } else {
       username = promptForName(username); // promptForName is blocking
     }
 
diff --git a/templates/HandlebarsTemplatePlugin.js b/templates/HandlebarsTemplatePlugin.js
index b80535744cb90d0cc5d12a3e9503e47c3d42bd2d..5c4278da369197060eb55c5db7c7ec5c5218d100 100644
--- a/templates/HandlebarsTemplatePlugin.js
+++ b/templates/HandlebarsTemplatePlugin.js
@@ -3,66 +3,76 @@ const fs = require("fs-extra");
 const path = require("path");
 const chokidar = require("chokidar");
 
+function filterUniqueTemplatePaths(pages) {
+  return pages
+    .map(page => page.templatePath)
+    .filter((fileName, index, arr) => arr.indexOf(fileName) === index);
+}
+
 class HandlebarsTemplatePlugin {
   constructor(options) {
-    this.templatesPath = options.templatesPath;
-    this.templateExtension = options.templateExtension || ".hbs";
-    this.templateOptions = options.templateOptions || {};
+    this.pages = options.pages;
 
     if (options.helpers) {
-      Object.keys(options.helpers).forEach(helperName => {
-        Handlebars.registerHelper(helperName, options.helpers[helperName]);
-      });
+      // Accepts an object where the key is the helper name and the value is the helper function
+      Handlebars.registerHelper(options.helpers);
     }
   }
 
   apply(compiler) {
+    // Trigger a webpack compilation whenerver the templates change
     compiler.plugin("watch-run", (compilation, callback) => {
-      chokidar
-        .watch(path.join(this.templatesPath, "*" + this.templateExtension))
-        .on("change", () => {
-          compiler.run(err => {
-            if (err) {
-              throw err;
-            }
-          });
+      const uniqueFiles = filterUniqueTemplatePaths(this.pages);
+
+      chokidar.watch(uniqueFiles).on("change", () => {
+        compiler.run(err => {
+          if (err) {
+            throw err;
+          }
         });
+      });
 
       callback();
     });
 
+    // Compile templates on each webpack compilation
     compiler.plugin("emit", (compilation, callback) => {
       this.compileTemplates(compiler, compilation).then(callback);
     });
   }
 
-  // Compile all handlebars templates in the template directory and place them in the output directory.
+  // Compile all handlebars templates in the template directory and place them in the output directory
   async compileTemplates(compiler, compilation) {
     const outputPath = compiler.options.output.path;
-    const templateFiles = await fs.readdir(this.templatesPath);
+    const uniqueTemplatePaths = filterUniqueTemplatePaths(this.pages);
+    const templatePromises = {};
 
-    const templatePromises = templateFiles
-      .filter(filename => filename.indexOf(this.templateExtension) !== -1)
-      .map(fileName => {
-        const filePath = path.join(this.templatesPath, fileName);
-        const outputFileName = fileName.replace(
-          this.templateExtension,
-          ".html"
-        );
-        const outputFilePath = path.join(outputPath, outputFileName);
+    // Compile all unique handlebars templates
+    for (const templatePath of uniqueTemplatePaths) {
+      templatePromises[templatePath] = async () => {
+        const templateStr = await fs.readFile(templatePath);
+        return Handlebars.compile(templateStr.toString());
+      };
+    }
 
-        return this.compileTemplate(filePath, outputFilePath);
-      });
+    // Use the compiled templates to generate the pages
+    const outputPromises = this.pages.map(async page => {
+      const template = await templatePromises[page.templatePath]();
+      const compiledStr = template({ ...page.data, compiler, compilation });
+      const outputFilePath = path.join(outputPath, page.fileName);
 
-    await Promise.all(templatePromises);
-  }
+      compilation.assets[page.fileName] = {
+        source() {
+          return compiledStr;
+        },
+        size() {
+          return compiledStr.length;
+        }
+      };
+    });
 
-  // Compile a single handlebars template given a file path and output file path.
-  async compileTemplate(filePath, outputFilePath) {
-    const templateStr = await fs.readFile(filePath);
-    const template = Handlebars.compile(templateStr.toString());
-    const compiledStr = template(this.templateOptions);
-    return fs.writeFile(outputFilePath, compiledStr);
+    // Compile templates in parallel
+    await Promise.all(outputPromises);
   }
 }
 
diff --git a/templates/helpers.js b/templates/helpers.js
new file mode 100644
index 0000000000000000000000000000000000000000..977777897feed59a21335fcf9f4d8fddc84ceab4
--- /dev/null
+++ b/templates/helpers.js
@@ -0,0 +1,43 @@
+const Handlebars = require("handlebars");
+const path = require("path");
+const fs = require("fs");
+const crc = require("crc");
+
+module.exports = {
+  /**
+   * Register a handlebars helper that prepends the base asset path.
+   * Useful for things like placing assets on a CDN and cache busting.
+   * Example:
+   * input: <img src="{{asset "asset.png"}}"/>
+   * output: <img src="https://cdn.mysite.com/asset.png?sha="/>
+   */
+  asset: (assetPath, options) => {
+    // In the development environment just use the original asset path.
+    if (process.env.NODE_ENV !== "production") {
+      return new Handlebars.SafeString(assetPath);
+    }
+
+    const compilation = options.data.root.compilation;
+
+    let asset;
+    if (compilation.assets[assetPath]) {
+      asset = compilation.assets[assetPath].source();
+    } else {
+      const outputPath = options.data.root.compiler.options.output.path;
+      const localPath = path.join(outputPath, assetPath);
+      asset = fs.readFileSync(localPath);
+    }
+
+    const hash = crc.crc32(asset).toString(16);
+
+    const baseAssetsPath = options.data.root.baseAssetsPath || "";
+    const cacheBustQueryString = "?crc=" + hash;
+
+    const url = baseAssetsPath + assetPath + cacheBustQueryString;
+
+    return new Handlebars.SafeString(url);
+  },
+  toJSON: obj => {
+    return new Handlebars.SafeString(JSON.stringify(obj));
+  }
+};
diff --git a/templates/index.hbs b/templates/index.hbs
index 391f3f5b872443b7bd66c78fe2e8211007bea706..a0e99d9819cf9b77a834fd6ce198ec75c4b8d6eb 100644
--- a/templates/index.hbs
+++ b/templates/index.hbs
@@ -7,11 +7,14 @@
     <meta name="viewport" content="width=device-width, initial-scale=1">
 
     <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
-    <link rel="stylesheet" href="https://code.getmdl.io/1.3.0/material.indigo-pink.min.css">
-    <script defer src="https://code.getmdl.io/1.3.0/material.min.js"></script>
+    <link rel="stylesheet" href="{{asset "lobby-vendor.css"}}">
+    <link rel="stylesheet" href="{{asset "lobby.css"}}">
+    <script src="{{asset "manifest.js"}}"></script>
+    <script src="{{asset "lobby-vendor.js"}}"></script>
   </head>
   <body>
       <div id="root"></div>
-      <script src="{{asset "lobby.bundle.js"}}"></script>
+      <script>window.CONFIG = {{toJSON config.global}};</script>
+      <script src="{{asset "lobby.js"}}"></script>
   </body>
 </html>
diff --git a/templates/room.hbs b/templates/room.hbs
index 92b4d9250bb8c33a054792719f072d168b487fdc..1d7e5a62b853ece12a680e30f8a2a90735458fdc 100644
--- a/templates/room.hbs
+++ b/templates/room.hbs
@@ -2,8 +2,18 @@
 
 <head>
     <title>Mozilla Mixed Reality Social Client</title>
-    <script src="https://webrtc.github.io/adapter/adapter-6.0.2.js"></script>
-    <script src="{{asset "app.bundle.js" }}"></script>
+
+    {{#if config.originTrialToken }}
+    <meta http-equiv="origin-trial" data-feature="WebVR (For Chrome M62+)" data-expires="{{ config.originTrialExpires }}" content="{{{ config.originTrialToken }}}">
+    {{/if}}
+
+    <link rel="stylesheet" href="{{asset "room.css"}}">
+
+    <script>window.CONFIG = {{toJSON config.global}};</script>
+    <script src="{{asset "manifest.js" }}"></script>
+    <script src="{{asset "room-vendor.js" }}"></script>
+    <script src="{{asset "room.js" }}"></script>
+    
     <style>
         .a-enter-vr {
             top: 90px;
diff --git a/webpack.common.js b/webpack.common.js
index 93329fbc47bfd7b0fb57b3f4d41d8e6a5b1b97c2..b9edde20bb6c9f246ff9804818405176771e48b6 100644
--- a/webpack.common.js
+++ b/webpack.common.js
@@ -1,14 +1,60 @@
 const path = require("path");
+const glob = require("glob");
+const webpack = require("webpack");
+const ExtractTextPlugin = require("extract-text-webpack-plugin");
+const CopyWebpackPlugin = require("copy-webpack-plugin");
+const CleanWebpackPlugin = require("clean-webpack-plugin");
 const HandlebarsTemplatePlugin = require("./templates/HandlebarsTemplatePlugin");
-const Handlebars = require("handlebars");
+const helpers = require("./templates/helpers");
+const config = require("./config");
+
+const templatePaths = glob.sync("./templates/*.hbs");
+const pages = [];
+
+for (const templatePath of templatePaths) {
+  const fileName = path.basename(templatePath, ".hbs");
+
+  // Generate html pages for each .hbs template in /templates
+  pages.push({
+    fileName: fileName + ".html",
+    templatePath,
+    data: {
+      baseAssetsPath: process.env.BASE_ASSETS_PATH,
+      config
+    }
+  });
+
+  // Generate html pages for smoke tests
+  if (process.env.GENERATE_SMOKE_TESTS) {
+    pages.push({
+      fileName: "smoke-" + fileName + ".html",
+      templatePath,
+      data: {
+        baseAssetsPath:
+          process.env.BASE_ASSETS_PATH &&
+          process.env.BASE_ASSETS_PATH.replace("https://", "https://smoke-"),
+        config: {
+          ...config,
+          global: {
+            ...config.global,
+            janus_server_url: config.global.janus_server_url.replace(
+              "wss://",
+              "wss://smoke-"
+            )
+          }
+        }
+      }
+    });
+  }
+}
 
 module.exports = {
   entry: {
-    app: path.join(__dirname, "src", "index"),
+    room: path.join(__dirname, "src", "room"),
     lobby: path.join(__dirname, "src", "lobby")
   },
   output: {
-    filename: "[name].bundle.js",
+    filename: "[name].js",
     path: path.resolve(__dirname, "public")
   },
   module: {
@@ -21,31 +67,65 @@ module.exports = {
       },
       {
         test: /\.css$/,
-        use: ["style-loader", "css-loader"]
+        use: ExtractTextPlugin.extract({
+          fallback: "style-loader",
+          use: "css-loader"
+        })
+      },
+      {
+        test: /\.(png|jpg|gif)$/,
+        use: {
+          loader: "file-loader",
+          options: {
+            emitFile: false,
+            outputPath(url) {
+              // Rewrite the url to correctly reference the copied assets directory.
+              return url.replace("src/assets/", "assets/");
+            },
+            name(file) {
+              if (process.env.NODE_ENV === "production") {
+                return "[path][name].[ext]?md5=[hash]";
+              }
+
+              return "[path][name].[ext]";
+            }
+          }
+        }
       }
     ]
   },
   plugins: [
-    new HandlebarsTemplatePlugin({
-      templatesPath: path.resolve(__dirname, "templates"),
-      helpers: {
-        /**
-         * Register a handlebars helper that prepends the base asset path.
-         * Useful for things like placing assets on a CDN and cache busting.
-         * Example:
-         * input: <img src="{{asset "asset.png"}}"/>
-         * output: <img src="https://cdn.mysite.com/asset.png?c="/>
-         */
-        asset: assetPath => {
-          const isProd = process.env.NODE_ENV === "production";
-          const baseAssetsPath = process.env.BASE_ASSETS_PATH || "/";
-          const cacheBustQueryString = isProd ? "?c=" + Date.now() : "";
-
-          const url = baseAssetsPath + assetPath + cacheBustQueryString;
-
-          return new Handlebars.SafeString(url);
-        }
+    new CleanWebpackPlugin("public"),
+    new CopyWebpackPlugin([
+      {
+        from: path.join(__dirname, "src", "assets"),
+        to: "assets"
+      }
+    ]),
+    new webpack.optimize.CommonsChunkPlugin({
+      name: "lobby-vendor",
+      chunks: ["lobby"],
+      minChunks: function(module) {
+        return module.context && module.context.indexOf("node_modules") !== -1;
       }
+    }),
+    new webpack.optimize.CommonsChunkPlugin({
+      name: "room-vendor",
+      chunks: ["room"],
+      minChunks: function(module) {
+        return module.context && module.context.indexOf("node_modules") !== -1;
+      }
+    }),
+    new webpack.optimize.CommonsChunkPlugin({
+      name: "manifest",
+      minChunks: Infinity
+    }),
+    new ExtractTextPlugin("[name].css", {
+      disable: process.env.NODE_ENV !== "production"
+    }),
+    new HandlebarsTemplatePlugin({
+      pages,
+      helpers
     })
   ]
 };
diff --git a/webpack.dev.js b/webpack.dev.js
index 0870af4865812b46fe43903cc46ede9cbc8fc669..a2c0f17bc3b88063beefe7e51e20f8b36bd7411a 100644
--- a/webpack.dev.js
+++ b/webpack.dev.js
@@ -1,11 +1,13 @@
 const path = require("path");
 const merge = require("webpack-merge");
 const common = require("./webpack.common");
+const WriteFilePlugin = require("write-file-webpack-plugin");
 
 module.exports = merge(common, {
   devtool: "inline-source-map",
   devServer: {
     contentBase: path.resolve(__dirname, "public"),
     disableHostCheck: true
-  }
+  },
+  plugins: [new WriteFilePlugin()]
 });
diff --git a/webpack.prod.js b/webpack.prod.js
index 71dc07a5f8d8fb113dd828beea273d0e9b833949..d4cc04fb816609026f9bcb5c14741eadb43f6784 100644
--- a/webpack.prod.js
+++ b/webpack.prod.js
@@ -1,8 +1,20 @@
+const webpack = require("webpack");
 const merge = require("webpack-merge");
-const MinifyPlugin = require("babel-minify-webpack-plugin");
+const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
+const OptimizeCssAssetsPlugin = require("optimize-css-assets-webpack-plugin");
+const ExtractTextPlugin = require("extract-text-webpack-plugin");
 const common = require("./webpack.common");
 
 module.exports = merge(common, {
   devtool: "source-map",
-  plugins: [new MinifyPlugin()]
+  plugins: [
+    new OptimizeCssAssetsPlugin(),
+    new UglifyJsPlugin({
+      parallel: true,
+      sourceMap: true
+    }),
+    new webpack.DefinePlugin({
+      "process.env.NODE_ENV": "'production'"
+    })
+  ]
 });
diff --git a/yarn.lock b/yarn.lock
index dc816124eadb963ef0d2716e533bb21deb14cc35..2ac1b78293faf903b52f32c787c4604d34d22282 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -182,7 +182,7 @@ anymatch@^1.3.0:
     micromatch "^2.1.5"
     normalize-path "^2.0.0"
 
-aproba@^1.0.3:
+aproba@^1.0.3, aproba@^1.1.1:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a"
 
@@ -310,7 +310,7 @@ async@^1.4.0, async@^1.5.2:
   version "1.5.2"
   resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a"
 
-async@^2.1.2:
+async@^2.1.2, async@^2.4.1:
   version "2.6.0"
   resolved "https://registry.yarnpkg.com/async/-/async-2.6.0.tgz#61a29abb6fcc026fea77e56d1c6ec53a795951f4"
   dependencies:
@@ -347,7 +347,7 @@ babel-code-frame@^6.11.0, babel-code-frame@^6.22.0, babel-code-frame@^6.26.0:
     esutils "^2.0.2"
     js-tokens "^3.0.2"
 
-babel-core@^6.24.1, 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:
@@ -418,10 +418,6 @@ babel-helper-define-map@^6.24.1:
     babel-types "^6.26.0"
     lodash "^4.17.4"
 
-babel-helper-evaluate-path@^0.2.0:
-  version "0.2.0"
-  resolved "https://registry.yarnpkg.com/babel-helper-evaluate-path/-/babel-helper-evaluate-path-0.2.0.tgz#0bb2eb01996c0cef53c5e8405e999fe4a0244c08"
-
 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"
@@ -430,10 +426,6 @@ babel-helper-explode-assignable-expression@^6.24.1:
     babel-traverse "^6.24.1"
     babel-types "^6.24.1"
 
-babel-helper-flip-expressions@^0.2.0:
-  version "0.2.0"
-  resolved "https://registry.yarnpkg.com/babel-helper-flip-expressions/-/babel-helper-flip-expressions-0.2.0.tgz#160d2090a3d9f9c64a750905321a0bc218f884ec"
-
 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"
@@ -458,18 +450,6 @@ babel-helper-hoist-variables@^6.24.1:
     babel-runtime "^6.22.0"
     babel-types "^6.24.1"
 
-babel-helper-is-nodes-equiv@^0.0.1:
-  version "0.0.1"
-  resolved "https://registry.yarnpkg.com/babel-helper-is-nodes-equiv/-/babel-helper-is-nodes-equiv-0.0.1.tgz#34e9b300b1479ddd98ec77ea0bbe9342dfe39684"
-
-babel-helper-is-void-0@^0.2.0:
-  version "0.2.0"
-  resolved "https://registry.yarnpkg.com/babel-helper-is-void-0/-/babel-helper-is-void-0-0.2.0.tgz#6ed0ada8a9b1c5b6e88af6b47c1b3b5c080860eb"
-
-babel-helper-mark-eval-scopes@^0.2.0:
-  version "0.2.0"
-  resolved "https://registry.yarnpkg.com/babel-helper-mark-eval-scopes/-/babel-helper-mark-eval-scopes-0.2.0.tgz#7648aaf2ec92aae9b09a20ad91e8df5e1fcc94b2"
-
 babel-helper-optimise-call-expression@^6.24.1:
   version "6.24.1"
   resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz#f7a13427ba9f73f8f4fa993c54a97882d1244257"
@@ -495,10 +475,6 @@ babel-helper-remap-async-to-generator@^6.24.1:
     babel-traverse "^6.24.1"
     babel-types "^6.24.1"
 
-babel-helper-remove-or-void@^0.2.0:
-  version "0.2.0"
-  resolved "https://registry.yarnpkg.com/babel-helper-remove-or-void/-/babel-helper-remove-or-void-0.2.0.tgz#8e46ad5b30560d57d7510b3fd93f332ee7c67386"
-
 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"
@@ -510,10 +486,6 @@ babel-helper-replace-supers@^6.24.1:
     babel-traverse "^6.24.1"
     babel-types "^6.24.1"
 
-babel-helper-to-multiple-sequence-expressions@^0.2.0:
-  version "0.2.0"
-  resolved "https://registry.yarnpkg.com/babel-helper-to-multiple-sequence-expressions/-/babel-helper-to-multiple-sequence-expressions-0.2.0.tgz#d1a419634c6cb301f27858c659167cfee0a9d318"
-
 babel-helpers@^6.24.1:
   version "6.24.1"
   resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2"
@@ -535,85 +507,12 @@ babel-messages@^6.23.0:
   dependencies:
     babel-runtime "^6.22.0"
 
-babel-minify-webpack-plugin@^0.2.0:
-  version "0.2.0"
-  resolved "https://registry.yarnpkg.com/babel-minify-webpack-plugin/-/babel-minify-webpack-plugin-0.2.0.tgz#ef9694d11a1b8ab8f3204d89f5c9278dd28fc2a9"
-  dependencies:
-    babel-core "^6.24.1"
-    babel-preset-minify "^0.2.0"
-    webpack-sources "^1.0.1"
-
 babel-plugin-check-es2015-constants@^6.22.0:
   version "6.22.0"
   resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz#35157b101426fd2ffd3da3f75c7d1e91835bbf8a"
   dependencies:
     babel-runtime "^6.22.0"
 
-babel-plugin-minify-builtins@^0.2.0:
-  version "0.2.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-minify-builtins/-/babel-plugin-minify-builtins-0.2.0.tgz#317f824b0907210b6348671bb040ca072e2e0c82"
-  dependencies:
-    babel-helper-evaluate-path "^0.2.0"
-
-babel-plugin-minify-constant-folding@^0.2.0:
-  version "0.2.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-minify-constant-folding/-/babel-plugin-minify-constant-folding-0.2.0.tgz#8c70b528b2eb7c13e94d95c8789077d4cdbc3970"
-  dependencies:
-    babel-helper-evaluate-path "^0.2.0"
-
-babel-plugin-minify-dead-code-elimination@^0.2.0:
-  version "0.2.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-minify-dead-code-elimination/-/babel-plugin-minify-dead-code-elimination-0.2.0.tgz#e8025ee10a1e5e4f202633a6928ce892c33747e3"
-  dependencies:
-    babel-helper-evaluate-path "^0.2.0"
-    babel-helper-mark-eval-scopes "^0.2.0"
-    babel-helper-remove-or-void "^0.2.0"
-    lodash.some "^4.6.0"
-
-babel-plugin-minify-flip-comparisons@^0.2.0:
-  version "0.2.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-minify-flip-comparisons/-/babel-plugin-minify-flip-comparisons-0.2.0.tgz#0c9c8e93155c8f09dedad8118b634c259f709ef5"
-  dependencies:
-    babel-helper-is-void-0 "^0.2.0"
-
-babel-plugin-minify-guarded-expressions@^0.2.0:
-  version "0.2.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-minify-guarded-expressions/-/babel-plugin-minify-guarded-expressions-0.2.0.tgz#8a8c950040fce3e258a12e6eb21eab94ad7235ab"
-  dependencies:
-    babel-helper-flip-expressions "^0.2.0"
-
-babel-plugin-minify-infinity@^0.2.0:
-  version "0.2.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-minify-infinity/-/babel-plugin-minify-infinity-0.2.0.tgz#30960c615ddbc657c045bb00a1d8eb4af257cf03"
-
-babel-plugin-minify-mangle-names@^0.2.0:
-  version "0.2.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-minify-mangle-names/-/babel-plugin-minify-mangle-names-0.2.0.tgz#719892297ff0106a6ec1a4b0fc062f1f8b6a8529"
-  dependencies:
-    babel-helper-mark-eval-scopes "^0.2.0"
-
-babel-plugin-minify-numeric-literals@^0.2.0:
-  version "0.2.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-minify-numeric-literals/-/babel-plugin-minify-numeric-literals-0.2.0.tgz#5746e851700167a380c05e93f289a7070459a0d1"
-
-babel-plugin-minify-replace@^0.2.0:
-  version "0.2.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-minify-replace/-/babel-plugin-minify-replace-0.2.0.tgz#3c1f06bc4e6d3e301eacb763edc1be611efc39b0"
-
-babel-plugin-minify-simplify@^0.2.0:
-  version "0.2.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-minify-simplify/-/babel-plugin-minify-simplify-0.2.0.tgz#21ceec4857100c5476d7cef121f351156e5c9bc0"
-  dependencies:
-    babel-helper-flip-expressions "^0.2.0"
-    babel-helper-is-nodes-equiv "^0.0.1"
-    babel-helper-to-multiple-sequence-expressions "^0.2.0"
-
-babel-plugin-minify-type-constructors@^0.2.0:
-  version "0.2.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-minify-type-constructors/-/babel-plugin-minify-type-constructors-0.2.0.tgz#7f3b6458be0863cfd59e9985bed6d134aa7a2e17"
-  dependencies:
-    babel-helper-is-void-0 "^0.2.0"
-
 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"
@@ -825,28 +724,6 @@ babel-plugin-transform-flow-strip-types@^6.22.0:
     babel-plugin-syntax-flow "^6.18.0"
     babel-runtime "^6.22.0"
 
-babel-plugin-transform-inline-consecutive-adds@^0.2.0:
-  version "0.2.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-inline-consecutive-adds/-/babel-plugin-transform-inline-consecutive-adds-0.2.0.tgz#15dae78921057f4004f8eafd79e15ddc5f12f426"
-
-babel-plugin-transform-member-expression-literals@^6.8.5:
-  version "6.8.5"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-member-expression-literals/-/babel-plugin-transform-member-expression-literals-6.8.5.tgz#e06ae305cf48d819822e93a70d79269f04d89eec"
-
-babel-plugin-transform-merge-sibling-variables@^6.8.6:
-  version "6.8.6"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-merge-sibling-variables/-/babel-plugin-transform-merge-sibling-variables-6.8.6.tgz#6d21efa5ee4981f71657fae716f9594bb2622aef"
-
-babel-plugin-transform-minify-booleans@^6.8.3:
-  version "6.8.3"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-minify-booleans/-/babel-plugin-transform-minify-booleans-6.8.3.tgz#5906ed776d3718250519abf1bace44b0b613ddf9"
-
-babel-plugin-transform-property-literals@^6.8.5:
-  version "6.8.5"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-property-literals/-/babel-plugin-transform-property-literals-6.8.5.tgz#67ed5930b34805443452c8b9690c7ebe1e206c40"
-  dependencies:
-    esutils "^2.0.2"
-
 babel-plugin-transform-react-display-name@^6.23.0:
   version "6.25.0"
   resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz#67e2bf1f1e9c93ab08db96792e05392bf2cc28d1"
@@ -881,28 +758,6 @@ babel-plugin-transform-regenerator@^6.22.0:
   dependencies:
     regenerator-transform "^0.10.0"
 
-babel-plugin-transform-regexp-constructors@^0.2.0:
-  version "0.2.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-regexp-constructors/-/babel-plugin-transform-regexp-constructors-0.2.0.tgz#6aa5dd0acc515db4be929bbcec4ed4c946c534a3"
-
-babel-plugin-transform-remove-console@^6.8.5:
-  version "6.8.5"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-remove-console/-/babel-plugin-transform-remove-console-6.8.5.tgz#fde9d2d3d725530b0fadd8d31078402410386810"
-
-babel-plugin-transform-remove-debugger@^6.8.5:
-  version "6.8.5"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-remove-debugger/-/babel-plugin-transform-remove-debugger-6.8.5.tgz#809584d412bf918f071fdf41e1fdb15ea89cdcd5"
-
-babel-plugin-transform-remove-undefined@^0.2.0:
-  version "0.2.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-remove-undefined/-/babel-plugin-transform-remove-undefined-0.2.0.tgz#94f052062054c707e8d094acefe79416b63452b1"
-  dependencies:
-    babel-helper-evaluate-path "^0.2.0"
-
-babel-plugin-transform-simplify-comparison-operators@^6.8.5:
-  version "6.8.5"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-simplify-comparison-operators/-/babel-plugin-transform-simplify-comparison-operators-6.8.5.tgz#a838786baf40cc33a93b95ae09e05591227e43bf"
-
 babel-plugin-transform-strict-mode@^6.24.1:
   version "6.24.1"
   resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz#d5faf7aa578a65bbe591cf5edae04a0c67020758"
@@ -910,10 +765,6 @@ babel-plugin-transform-strict-mode@^6.24.1:
     babel-runtime "^6.22.0"
     babel-types "^6.24.1"
 
-babel-plugin-transform-undefined-to-void@^6.8.3:
-  version "6.8.3"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-undefined-to-void/-/babel-plugin-transform-undefined-to-void-6.8.3.tgz#fc52707f6ee1ddc71bb91b0d314fbefdeef9beb4"
-
 babel-preset-env@^1.6.1:
   version "1.6.1"
   resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.6.1.tgz#a18b564cc9b9afdf4aae57ae3c1b0d99188e6f48"
@@ -955,34 +806,6 @@ babel-preset-flow@^6.23.0:
   dependencies:
     babel-plugin-transform-flow-strip-types "^6.22.0"
 
-babel-preset-minify@^0.2.0:
-  version "0.2.0"
-  resolved "https://registry.yarnpkg.com/babel-preset-minify/-/babel-preset-minify-0.2.0.tgz#006566552d9b83834472273f306c0131062a0acc"
-  dependencies:
-    babel-plugin-minify-builtins "^0.2.0"
-    babel-plugin-minify-constant-folding "^0.2.0"
-    babel-plugin-minify-dead-code-elimination "^0.2.0"
-    babel-plugin-minify-flip-comparisons "^0.2.0"
-    babel-plugin-minify-guarded-expressions "^0.2.0"
-    babel-plugin-minify-infinity "^0.2.0"
-    babel-plugin-minify-mangle-names "^0.2.0"
-    babel-plugin-minify-numeric-literals "^0.2.0"
-    babel-plugin-minify-replace "^0.2.0"
-    babel-plugin-minify-simplify "^0.2.0"
-    babel-plugin-minify-type-constructors "^0.2.0"
-    babel-plugin-transform-inline-consecutive-adds "^0.2.0"
-    babel-plugin-transform-member-expression-literals "^6.8.5"
-    babel-plugin-transform-merge-sibling-variables "^6.8.6"
-    babel-plugin-transform-minify-booleans "^6.8.3"
-    babel-plugin-transform-property-literals "^6.8.5"
-    babel-plugin-transform-regexp-constructors "^0.2.0"
-    babel-plugin-transform-remove-console "^6.8.5"
-    babel-plugin-transform-remove-debugger "^6.8.5"
-    babel-plugin-transform-remove-undefined "^0.2.0"
-    babel-plugin-transform-simplify-comparison-operators "^6.8.5"
-    babel-plugin-transform-undefined-to-void "^6.8.3"
-    lodash.isplainobject "^4.0.6"
-
 babel-preset-react@^6.24.1:
   version "6.24.1"
   resolved "https://registry.yarnpkg.com/babel-preset-react/-/babel-preset-react-6.24.1.tgz#ba69dfaea45fc3ec639b6a4ecea6e17702c91380"
@@ -1112,6 +935,10 @@ block-stream@*:
   dependencies:
     inherits "~2.0.0"
 
+bluebird@^3.5.0, bluebird@^3.5.1:
+  version "3.5.1"
+  resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9"
+
 bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0:
   version "4.11.8"
   resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f"
@@ -1282,6 +1109,24 @@ bytes@3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048"
 
+cacache@^10.0.0:
+  version "10.0.1"
+  resolved "https://registry.yarnpkg.com/cacache/-/cacache-10.0.1.tgz#3e05f6e616117d9b54665b1b20c8aeb93ea5d36f"
+  dependencies:
+    bluebird "^3.5.0"
+    chownr "^1.0.1"
+    glob "^7.1.2"
+    graceful-fs "^4.1.11"
+    lru-cache "^4.1.1"
+    mississippi "^1.3.0"
+    mkdirp "^0.5.1"
+    move-concurrently "^1.0.1"
+    promise-inflight "^1.0.1"
+    rimraf "^2.6.1"
+    ssri "^5.0.0"
+    unique-filename "^1.1.0"
+    y18n "^3.2.1"
+
 caller-path@^0.1.0:
   version "0.1.0"
   resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f"
@@ -1351,7 +1196,7 @@ center-align@^0.1.1:
     align-text "^0.1.3"
     lazy-cache "^1.0.3"
 
-chalk@^1.1.3:
+chalk@^1.1.1, chalk@^1.1.3:
   version "1.1.3"
   resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
   dependencies:
@@ -1388,6 +1233,10 @@ chokidar@^1.6.0, chokidar@^1.7.0:
   optionalDependencies:
     fsevents "^1.0.0"
 
+chownr@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.0.1.tgz#e2a75042a9551908bebd25b8523d5f9769d79181"
+
 cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3:
   version "1.0.4"
   resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de"
@@ -1411,6 +1260,12 @@ clean-css@2.2.x:
   dependencies:
     commander "2.2.x"
 
+clean-webpack-plugin@^0.1.17:
+  version "0.1.17"
+  resolved "https://registry.yarnpkg.com/clean-webpack-plugin/-/clean-webpack-plugin-0.1.17.tgz#71c57242e6d47204d46f809413176e7bed28ec49"
+  dependencies:
+    rimraf "^2.6.1"
+
 cli-cursor@^2.1.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5"
@@ -1505,6 +1360,10 @@ commander@^2.5.0:
   version "2.11.0"
   resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563"
 
+commander@~2.12.1:
+  version "2.12.2"
+  resolved "https://registry.yarnpkg.com/commander/-/commander-2.12.2.tgz#0f5946c427ed9ec0d91a46bb9def53e54650e555"
+
 commondir@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
@@ -1569,7 +1428,7 @@ concat-stream@1.4.x:
     readable-stream "~1.1.9"
     typedarray "~0.0.5"
 
-concat-stream@^1.6.0:
+concat-stream@^1.5.0, concat-stream@^1.6.0:
   version "1.6.0"
   resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.0.tgz#0aac662fd52be78964d5532f694784e70110acf7"
   dependencies:
@@ -1615,6 +1474,28 @@ cookie@0.3.1:
   version "0.3.1"
   resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb"
 
+copy-concurrently@^1.0.0:
+  version "1.0.5"
+  resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0"
+  dependencies:
+    aproba "^1.1.1"
+    fs-write-stream-atomic "^1.0.8"
+    iferr "^0.1.5"
+    mkdirp "^0.5.1"
+    rimraf "^2.5.4"
+    run-queue "^1.0.0"
+
+copy-webpack-plugin@^4.2.3:
+  version "4.2.3"
+  resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-4.2.3.tgz#4a3c61089f3b635777f0f0af346c338b39d63755"
+  dependencies:
+    bluebird "^3.5.1"
+    glob "^7.1.2"
+    is-glob "^4.0.0"
+    loader-utils "^0.2.15"
+    lodash "^4.3.0"
+    minimatch "^3.0.4"
+
 core-js@^1.0.0:
   version "1.2.7"
   resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636"
@@ -1627,6 +1508,10 @@ core-util-is@1.0.2, core-util-is@~1.0.0:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
 
+crc@^3.5.0:
+  version "3.5.0"
+  resolved "https://registry.yarnpkg.com/crc/-/crc-3.5.0.tgz#98b8ba7d489665ba3979f59b21381374101a1964"
+
 create-ecdh@^4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.0.tgz#888c723596cdf7612f6498233eebd7a35301737d"
@@ -1654,6 +1539,13 @@ create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4:
     safe-buffer "^5.0.1"
     sha.js "^2.4.8"
 
+cross-env@^5.1.1:
+  version "5.1.1"
+  resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-5.1.1.tgz#b6d8ab97f304c0f71dae7277b75fe424c08dfa74"
+  dependencies:
+    cross-spawn "^5.1.0"
+    is-windows "^1.0.0"
+
 cross-spawn@^5.0.1, cross-spawn@^5.1.0:
   version "5.1.0"
   resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449"
@@ -1736,7 +1628,7 @@ cssesc@^0.1.0:
   version "0.1.0"
   resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-0.1.0.tgz#c814903e45623371a0477b40109aaafbeeaddbb4"
 
-"cssnano@>=2.6.1 <4":
+"cssnano@>=2.6.1 <4", cssnano@^3.4.0:
   version "3.10.0"
   resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-3.10.0.tgz#4f38f6cea2b9b17fa01490f23f1dc68ea65c1c38"
   dependencies:
@@ -1786,6 +1678,10 @@ currently-unhandled@^0.4.1:
   dependencies:
     array-find-index "^1.0.1"
 
+cyclist@~0.2.2:
+  version "0.2.2"
+  resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640"
+
 d@1:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/d/-/d-1.0.0.tgz#754bb5bfe55451da69a58b94d45f4c5b0462d58f"
@@ -1994,6 +1890,15 @@ dtype@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/dtype/-/dtype-2.0.0.tgz#cd052323ce061444ecd2e8f5748f69a29be28434"
 
+duplexify@^3.1.2, duplexify@^3.4.2:
+  version "3.5.1"
+  resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.5.1.tgz#4e1516be68838bc90a49994f0b39a6e5960befcd"
+  dependencies:
+    end-of-stream "^1.0.0"
+    inherits "^2.0.1"
+    readable-stream "^2.0.0"
+    stream-shift "^1.0.0"
+
 easyrtc@1.1.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/easyrtc/-/easyrtc-1.1.0.tgz#f44937f7132cb8b5ba8e0bc1cc3e3ccc472a3ef4"
@@ -2042,6 +1947,12 @@ encoding@^0.1.11:
   dependencies:
     iconv-lite "~0.4.13"
 
+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"
+
 engine.io-client@~1.8.4:
   version "1.8.4"
   resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-1.8.4.tgz#9fe85dee25853ca6babe25bd2ad68710863e91c2"
@@ -2097,7 +2008,7 @@ envify@^3.4.1:
     jstransform "^11.0.3"
     through "~2.3.4"
 
-errno@^0.1.3:
+errno@^0.1.3, errno@^0.1.4:
   version "0.1.4"
   resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.4.tgz#b896e23a9e5e8ba33871fc996abd3635fc9a1c7d"
   dependencies:
@@ -2431,6 +2342,15 @@ extglob@^0.3.1:
   dependencies:
     is-extglob "^1.0.0"
 
+extract-text-webpack-plugin@^3.0.2:
+  version "3.0.2"
+  resolved "https://registry.yarnpkg.com/extract-text-webpack-plugin/-/extract-text-webpack-plugin-3.0.2.tgz#5f043eaa02f9750a9258b78c0a6e0dc1408fb2f7"
+  dependencies:
+    async "^2.4.1"
+    loader-utils "^1.1.0"
+    schema-utils "^0.3.0"
+    webpack-sources "^1.0.1"
+
 extsprintf@1.3.0, extsprintf@^1.2.0:
   version "1.3.0"
   resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05"
@@ -2492,10 +2412,21 @@ file-entry-cache@^2.0.0:
     flat-cache "^1.2.1"
     object-assign "^4.0.1"
 
+file-loader@^1.1.5:
+  version "1.1.5"
+  resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-1.1.5.tgz#91c25b6b6fbe56dae99f10a425fd64933b5c9daa"
+  dependencies:
+    loader-utils "^1.0.2"
+    schema-utils "^0.3.0"
+
 filename-regex@^2.0.0:
   version "2.0.1"
   resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26"
 
+filesize@^3.2.1:
+  version "3.5.11"
+  resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.5.11.tgz#1919326749433bb3cf77368bd158caabcc19e9ee"
+
 fill-range@^2.1.0:
   version "2.2.3"
   resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.3.tgz#50b77dfd7e469bc7492470963699fe7a8485a723"
@@ -2576,6 +2507,13 @@ flatten@^1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782"
 
+flush-write-stream@^1.0.0:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.0.2.tgz#c81b90d8746766f1a609a46809946c45dd8ae417"
+  dependencies:
+    inherits "^2.0.1"
+    readable-stream "^2.0.4"
+
 for-each@^0.3.2:
   version "0.3.2"
   resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.2.tgz#2c40450b9348e97f281322593ba96704b9abd4d4"
@@ -2616,6 +2554,13 @@ fresh@0.5.2:
   version "0.5.2"
   resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
 
+from2@^2.1.0:
+  version "2.3.0"
+  resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af"
+  dependencies:
+    inherits "^2.0.1"
+    readable-stream "^2.0.0"
+
 fs-exists-sync@^0.1.0:
   version "0.1.0"
   resolved "https://registry.yarnpkg.com/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz#982d6893af918e72d08dec9e8673ff2b5a8d6add"
@@ -2628,6 +2573,15 @@ fs-extra@^4.0.2:
     jsonfile "^4.0.0"
     universalify "^0.1.0"
 
+fs-write-stream-atomic@^1.0.8:
+  version "1.0.10"
+  resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9"
+  dependencies:
+    graceful-fs "^4.1.2"
+    iferr "^0.1.5"
+    imurmurhash "^0.1.4"
+    readable-stream "1 || 2"
+
 fs.realpath@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
@@ -2788,7 +2742,7 @@ globby@^6.1.0:
     pify "^2.0.0"
     pinkie-promise "^2.0.0"
 
-graceful-fs@^4.1.2, graceful-fs@^4.1.6:
+graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6:
   version "4.1.11"
   resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658"
 
@@ -2989,6 +2943,10 @@ ieee754@^1.1.4:
   version "1.1.8"
   resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.8.tgz#be33d40ac10ef1926701f6f08a2d86fbfd1ad3e4"
 
+iferr@^0.1.5:
+  version "0.1.5"
+  resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501"
+
 ignore@^3.3.3:
   version "3.3.7"
   resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.7.tgz#612289bfb3c220e186a58118618d5be8c1bab021"
@@ -3134,7 +3092,7 @@ is-extglob@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0"
 
-is-extglob@^2.1.0:
+is-extglob@^2.1.0, is-extglob@^2.1.1:
   version "2.1.1"
   resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
 
@@ -3170,6 +3128,12 @@ is-glob@^3.1.0:
   dependencies:
     is-extglob "^2.1.0"
 
+is-glob@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.0.tgz#9521c76845cc2610a85203ddf080a958c2ffabc0"
+  dependencies:
+    is-extglob "^2.1.1"
+
 is-number@^2.1.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f"
@@ -3256,6 +3220,10 @@ is-windows@^0.2.0:
   version "0.2.0"
   resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-0.2.0.tgz#de1aa6d63ea29dd248737b69f1ff8b8002d2108c"
 
+is-windows@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.1.tgz#310db70f742d259a16a369202b51af84233310d9"
+
 is-wsl@^1.1.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d"
@@ -3406,6 +3374,13 @@ kind-of@^4.0.0:
   dependencies:
     is-buffer "^1.1.5"
 
+last-call-webpack-plugin@^2.1.2:
+  version "2.1.2"
+  resolved "https://registry.yarnpkg.com/last-call-webpack-plugin/-/last-call-webpack-plugin-2.1.2.tgz#ad80c6e310998294d2ed2180a68e9589e4768c44"
+  dependencies:
+    lodash "^4.17.4"
+    webpack-sources "^1.0.1"
+
 layout-bmfont-text@^1.2.0:
   version "1.3.4"
   resolved "https://registry.yarnpkg.com/layout-bmfont-text/-/layout-bmfont-text-1.3.4.tgz#f20f2c5464774f48da6ce8a997fbce6d46945b81"
@@ -3466,6 +3441,15 @@ loader-runner@^2.3.0:
   version "2.3.0"
   resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.3.0.tgz#f482aea82d543e07921700d5a46ef26fdac6b8a2"
 
+loader-utils@^0.2.15:
+  version "0.2.17"
+  resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-0.2.17.tgz#f86e6374d43205a6e6c60e9196f17c0299bfb348"
+  dependencies:
+    big.js "^3.1.3"
+    emojis-list "^2.0.0"
+    json5 "^0.5.0"
+    object-assign "^4.0.1"
+
 loader-utils@^1.0.2, loader-utils@^1.1.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.1.0.tgz#c98aef488bcceda2ffb5e2de646d6a754429f5cd"
@@ -3485,18 +3469,10 @@ lodash.camelcase@^4.3.0:
   version "4.3.0"
   resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6"
 
-lodash.isplainobject@^4.0.6:
-  version "4.0.6"
-  resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb"
-
 lodash.memoize@^4.1.2:
   version "4.1.2"
   resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe"
 
-lodash.some@^4.6.0:
-  version "4.6.0"
-  resolved "https://registry.yarnpkg.com/lodash.some/-/lodash.some-4.6.0.tgz#1bb9f314ef6b8baded13b549169b2a945eb68e4d"
-
 lodash.uniq@^4.5.0:
   version "4.5.0"
   resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
@@ -3505,7 +3481,7 @@ lodash@3.6.x:
   version "3.6.0"
   resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.6.0.tgz#5266a8f49dd989be4f9f681b6f2a0c55285d0d9a"
 
-lodash@^4.14.0, lodash@^4.17.2, lodash@^4.17.4, lodash@^4.3.0:
+lodash@^4.14.0, lodash@^4.17.2, lodash@^4.17.4, lodash@^4.3.0, lodash@^4.5.1:
   version "4.17.4"
   resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"
 
@@ -3534,7 +3510,7 @@ lru-cache@2:
   version "2.7.3"
   resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.7.3.tgz#6d4524e8b955f95d4f5b58851ce21dd72fb4e952"
 
-lru-cache@^4.0.1:
+lru-cache@^4.0.1, lru-cache@^4.1.1:
   version "4.1.1"
   resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.1.tgz#622e32e82488b49279114a4f9ecf45e7cd6bba55"
   dependencies:
@@ -3561,6 +3537,10 @@ 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"
 
+material-design-lite@^1.3.0:
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/material-design-lite/-/material-design-lite-1.3.0.tgz#d004ce3fee99a1eeb74a78b8a325134a5f1171d3"
+
 math-expression-evaluator@^1.2.14:
   version "1.2.17"
   resolved "https://registry.yarnpkg.com/math-expression-evaluator/-/math-expression-evaluator-1.2.17.tgz#de819fdbcd84dccd8fae59c6aeb79615b9d266ac"
@@ -3706,12 +3686,42 @@ minimist@~0.0.1:
   version "0.0.10"
   resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf"
 
+mississippi@^1.3.0:
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-1.3.0.tgz#d201583eb12327e3c5c1642a404a9cacf94e34f5"
+  dependencies:
+    concat-stream "^1.5.0"
+    duplexify "^3.4.2"
+    end-of-stream "^1.1.0"
+    flush-write-stream "^1.0.0"
+    from2 "^2.1.0"
+    parallel-transform "^1.1.0"
+    pump "^1.0.0"
+    pumpify "^1.3.3"
+    stream-each "^1.1.0"
+    through2 "^2.0.0"
+
 mkdirp@0.5.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1:
   version "0.5.1"
   resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
   dependencies:
     minimist "0.0.8"
 
+moment@^2.11.2:
+  version "2.19.3"
+  resolved "https://registry.yarnpkg.com/moment/-/moment-2.19.3.tgz#bdb99d270d6d7fda78cc0fbace855e27fe7da69f"
+
+move-concurrently@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92"
+  dependencies:
+    aproba "^1.1.1"
+    copy-concurrently "^1.0.0"
+    fs-write-stream-atomic "^1.0.8"
+    mkdirp "^0.5.1"
+    rimraf "^2.5.4"
+    run-queue "^1.0.3"
+
 ms@0.7.2:
   version "0.7.2"
   resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.2.tgz#ae25cf2512b3885a1d95d7f037868d8431124765"
@@ -3949,7 +3959,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.3.0, once@^1.3.1, 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:
@@ -3980,6 +3990,13 @@ optimist@^0.6.1:
     minimist "~0.0.1"
     wordwrap "~0.0.2"
 
+optimize-css-assets-webpack-plugin@^3.2.0:
+  version "3.2.0"
+  resolved "https://registry.yarnpkg.com/optimize-css-assets-webpack-plugin/-/optimize-css-assets-webpack-plugin-3.2.0.tgz#09a40c4cefde1dd0142444a873c56aa29eb18e6f"
+  dependencies:
+    cssnano "^3.4.0"
+    last-call-webpack-plugin "^2.1.2"
+
 optionator@^0.8.2:
   version "0.8.2"
   resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64"
@@ -4056,6 +4073,14 @@ pako@~1.0.5:
   version "1.0.6"
   resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.6.tgz#0101211baa70c4bca4a0f63f2206e97b7dfaf258"
 
+parallel-transform@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/parallel-transform/-/parallel-transform-1.1.0.tgz#d410f065b05da23081fcd10f28854c29bda33b06"
+  dependencies:
+    cyclist "~0.2.2"
+    inherits "^2.0.3"
+    readable-stream "^2.1.5"
+
 parse-asn1@^5.0.0:
   version "5.1.0"
   resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.0.tgz#37c4f9b7ed3ab65c74817b5f2480937fbf97c712"
@@ -4509,6 +4534,10 @@ progress@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.0.tgz#8a1be366bf8fc23db2bd23f10c6fe920b4389d1f"
 
+promise-inflight@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3"
+
 promise-polyfill@^3.1.0:
   version "3.1.0"
   resolved "https://registry.yarnpkg.com/promise-polyfill/-/promise-polyfill-3.1.0.tgz#62952b01d059b115b432763b7ef461b80f6df47d"
@@ -4552,6 +4581,21 @@ public-encrypt@^4.0.0:
     parse-asn1 "^5.0.0"
     randombytes "^2.0.1"
 
+pump@^1.0.0:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/pump/-/pump-1.0.3.tgz#5dfe8311c33bbf6fc18261f9f34702c47c08a954"
+  dependencies:
+    end-of-stream "^1.1.0"
+    once "^1.3.1"
+
+pumpify@^1.3.3:
+  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.3.2:
   version "1.3.2"
   resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d"
@@ -4707,16 +4751,7 @@ read-pkg@^2.0.0:
     normalize-package-data "^2.3.2"
     path-type "^2.0.0"
 
-"readable-stream@>=1.0.33-1 <1.1.0-0":
-  version "1.0.34"
-  resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c"
-  dependencies:
-    core-util-is "~1.0.0"
-    inherits "~2.0.1"
-    isarray "0.0.1"
-    string_decoder "~0.10.x"
-
-readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.2.2, readable-stream@^2.2.6, readable-stream@^2.2.9, readable-stream@^2.3.3:
+"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.2.6, readable-stream@^2.2.9, readable-stream@^2.3.3:
   version "2.3.3"
   resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c"
   dependencies:
@@ -4728,6 +4763,15 @@ readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable
     string_decoder "~1.0.3"
     util-deprecate "~1.0.1"
 
+"readable-stream@>=1.0.33-1 <1.1.0-0":
+  version "1.0.34"
+  resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c"
+  dependencies:
+    core-util-is "~1.0.0"
+    inherits "~2.0.1"
+    isarray "0.0.1"
+    string_decoder "~0.10.x"
+
 readable-stream@~1.1.9:
   version "1.1.14"
   resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9"
@@ -4928,7 +4972,7 @@ right-align@^0.1.1:
   dependencies:
     align-text "^0.1.1"
 
-rimraf@2, rimraf@^2.2.8, rimraf@^2.5.1, rimraf@^2.6.1:
+rimraf@2, rimraf@^2.2.8, rimraf@^2.5.1, rimraf@^2.5.4, rimraf@^2.6.1:
   version "2.6.2"
   resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36"
   dependencies:
@@ -4941,12 +4985,24 @@ ripemd160@^2.0.0, ripemd160@^2.0.1:
     hash-base "^2.0.0"
     inherits "^2.0.1"
 
+rtcpeerconnection-shim@^1.1.13:
+  version "1.2.2"
+  resolved "https://registry.yarnpkg.com/rtcpeerconnection-shim/-/rtcpeerconnection-shim-1.2.2.tgz#67511fafe4fcacf2bc357198f6bc1eede7a7ef46"
+  dependencies:
+    sdp "^2.2.0"
+
 run-async@^2.2.0:
   version "2.3.0"
   resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0"
   dependencies:
     is-promise "^2.1.0"
 
+run-queue@^1.0.0, run-queue@^1.0.3:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47"
+  dependencies:
+    aproba "^1.1.1"
+
 rx-lite-aggregates@^4.0.8:
   version "4.0.8"
   resolved "https://registry.yarnpkg.com/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz#753b87a89a11c95467c4ac1626c4efc4e05c67be"
@@ -4971,6 +5027,10 @@ schema-utils@^0.3.0:
   dependencies:
     ajv "^5.0.0"
 
+sdp@^2.2.0, sdp@^2.3.0:
+  version "2.5.0"
+  resolved "https://registry.yarnpkg.com/sdp/-/sdp-2.5.0.tgz#b15a0b1dfd0a38f6a8c780e58f8c8fe73c29ffe5"
+
 select-hose@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca"
@@ -5181,7 +5241,7 @@ source-map@^0.5.3, source-map@^0.5.6, source-map@~0.5.0, source-map@~0.5.1, sour
   version "0.5.7"
   resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
 
-source-map@^0.6.1:
+source-map@^0.6.1, source-map@~0.6.1:
   version "0.6.1"
   resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
 
@@ -5246,6 +5306,12 @@ sshpk@^1.7.0:
     jsbn "~0.1.0"
     tweetnacl "~0.14.0"
 
+ssri@^5.0.0:
+  version "5.0.0"
+  resolved "https://registry.yarnpkg.com/ssri/-/ssri-5.0.0.tgz#13c19390b606c821f2a10d02b351c1729b94d8cf"
+  dependencies:
+    safe-buffer "^5.1.0"
+
 "statuses@>= 1.3.1 < 2":
   version "1.4.0"
   resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087"
@@ -5261,6 +5327,13 @@ stream-browserify@^2.0.1:
     inherits "~2.0.1"
     readable-stream "^2.0.2"
 
+stream-each@^1.1.0:
+  version "1.2.2"
+  resolved "https://registry.yarnpkg.com/stream-each/-/stream-each-1.2.2.tgz#8e8c463f91da8991778765873fe4d960d8f616bd"
+  dependencies:
+    end-of-stream "^1.1.0"
+    stream-shift "^1.0.0"
+
 stream-http@^2.7.2:
   version "2.7.2"
   resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.7.2.tgz#40a050ec8dc3b53b33d9909415c02c0bf1abfbad"
@@ -5271,6 +5344,10 @@ stream-http@^2.7.2:
     to-arraybuffer "^1.0.0"
     xtend "^4.0.0"
 
+stream-shift@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952"
+
 strict-uri-encode@^1.0.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713"
@@ -5468,6 +5545,13 @@ through2@0.6.x:
     readable-stream ">=1.0.33-1 <1.1.0-0"
     xtend ">=4.0.0 <4.1.0-0"
 
+through2@^2.0.0:
+  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.3.6, through@~2.3.4:
   version "2.3.8"
   resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
@@ -5565,6 +5649,13 @@ ua-parser-js@^0.7.9:
   version "0.7.17"
   resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.17.tgz#e9ec5f9498b9ec910e7ae3ac626a805c4d09ecac"
 
+uglify-es@^3.2.0:
+  version "3.2.1"
+  resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.2.1.tgz#93de0aad8a1bb629c8a316f686351bc4d6ece687"
+  dependencies:
+    commander "~2.12.1"
+    source-map "~0.6.1"
+
 uglify-js@^2.6, uglify-js@^2.8.29:
   version "2.8.29"
   resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd"
@@ -5586,6 +5677,18 @@ uglifyjs-webpack-plugin@^0.4.6:
     uglify-js "^2.8.29"
     webpack-sources "^1.0.1"
 
+uglifyjs-webpack-plugin@^1.1.2:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-1.1.2.tgz#8a9abc238d01a33daaf86fa9a84c7ebc1e67b0f9"
+  dependencies:
+    cacache "^10.0.0"
+    find-cache-dir "^1.0.0"
+    schema-utils "^0.3.0"
+    source-map "^0.6.1"
+    uglify-es "^3.2.0"
+    webpack-sources "^1.0.1"
+    worker-farm "^1.4.1"
+
 uid-number@^0.0.6:
   version "0.0.6"
   resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81"
@@ -5612,6 +5715,18 @@ uniqs@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/uniqs/-/uniqs-2.0.0.tgz#ffede4b36b25290696e6e165d4a59edb998e6b02"
 
+unique-filename@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.0.tgz#d05f2fe4032560871f30e93cbe735eea201514f3"
+  dependencies:
+    unique-slug "^2.0.0"
+
+unique-slug@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.0.tgz#db6676e7c7cc0629878ff196097c78855ae9f4ab"
+  dependencies:
+    imurmurhash "^0.1.4"
+
 universalify@^0.1.0:
   version "0.1.1"
   resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.1.tgz#fa71badd4437af4c148841e3b3b165f9e9e590b7"
@@ -5796,6 +5911,13 @@ webpack@^3.6.0:
     webpack-sources "^1.0.1"
     yargs "^8.0.2"
 
+webrtc-adapter@^6.0.2:
+  version "6.0.2"
+  resolved "https://registry.yarnpkg.com/webrtc-adapter/-/webrtc-adapter-6.0.2.tgz#765f99c163e46046a758fec457f7859c90a19487"
+  dependencies:
+    rtcpeerconnection-shim "^1.1.13"
+    sdp "^2.3.0"
+
 websocket-driver@>=0.5.1:
   version "0.7.0"
   resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.0.tgz#0caf9d2d755d93aee049d4bdd0d3fe2cca2a24eb"
@@ -5859,6 +5981,13 @@ wordwrap@~1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb"
 
+worker-farm@^1.4.1:
+  version "1.5.2"
+  resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.5.2.tgz#32b312e5dc3d5d45d79ef44acc2587491cd729ae"
+  dependencies:
+    errno "^0.1.4"
+    xtend "^4.0.1"
+
 wrap-ansi@^2.0.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85"
@@ -5870,6 +5999,17 @@ wrappy@1:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
 
+write-file-webpack-plugin@^4.2.0:
+  version "4.2.0"
+  resolved "https://registry.yarnpkg.com/write-file-webpack-plugin/-/write-file-webpack-plugin-4.2.0.tgz#7bd18547eaa0ea0b23992fb1e0322e5431d339ef"
+  dependencies:
+    chalk "^1.1.1"
+    debug "^2.6.8"
+    filesize "^3.2.1"
+    lodash "^4.5.1"
+    mkdirp "^0.5.1"
+    moment "^2.11.2"
+
 write@^0.2.1:
   version "0.2.1"
   resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757"
@@ -5934,7 +6074,7 @@ 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.0 <4.1.0-0", xtend@^4.0.0:
+"xtend@>=4.0.0 <4.1.0-0", 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"