diff --git a/.babelrc b/.babelrc
index 24e18ca9127abe2a65a5a3a97cc470ecab6ca971..c13c5f627fd143c64d90f2d8c730dc752d89ace7 100644
--- a/.babelrc
+++ b/.babelrc
@@ -1,3 +1,3 @@
 {
-  "presets": ["node6"]
+  "presets": ["es2015"]
 }
diff --git a/.gitignore b/.gitignore
index abc20edbbb6214fd8317db9cfe487b126d7c20d3..a1676971c459613f245a3171f9035040d9c3b644 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
 *.swp
 npm-debug.log
 node_modules
+modules
diff --git a/main.js b/main.js
index a6191c048acd136ea68339ce31a99475c8dff6c6..c1b7643b3840b062ba886ee1173d5860502bc1c6 100644
--- a/main.js
+++ b/main.js
@@ -1,44 +1 @@
-/* eslint no-console: 0 */
-const express = require('express');
-const app = express();
-const server = require('http').Server(app);
-const io = require('socket.io')(server);
-
-server.listen(8000);
-
-app.use(express.static(`${__dirname }/public`));
-
-const instanceClients = [];
-io.on('connection', (socket) => {
-    socket.on('ident', (client) => {
-        if (instanceClients.indexOf(client) === -1) {
-            instanceClients.push(client);
-            socket.emit('meta', 'reload');
-        }
-    });
-});
-
-function endsWith(str, suffix) {
-    return str.indexOf(suffix, str.length - suffix.length) !== -1;
-}
-
-// for reasons
-global.DOW = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
-global.pad = function(n, width, z = '0') {
-    // eslint-disable-next-line
-    n = String(n);
-    return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n;
-};
-
-const normalizedPath = require('path').join(__dirname, 'modules');
-require('fs').readdirSync(normalizedPath).forEach((file) => {
-    if (endsWith(file, '.js')) {
-        try {
-            require(`./modules/${ file}`)(io);
-            console.log(`${file} loaded`);
-        } catch (e) {
-            console.log(`Error loading ${file}`);
-            console.log(e);
-        }
-    }
-});
+require('./modules/main.js');
diff --git a/modules/brand.js b/modules/brand.js
deleted file mode 100644
index 9a53f2620cf08add3dc41caacb39d2c1635a3062..0000000000000000000000000000000000000000
--- a/modules/brand.js
+++ /dev/null
@@ -1,69 +0,0 @@
-'use strict';
-
-var _fs = require('fs');
-
-var _fs2 = _interopRequireDefault(_fs);
-
-var _httpreq = require('httpreq');
-
-var _httpreq2 = _interopRequireDefault(_httpreq);
-
-var _Mustache = require('Mustache');
-
-var _Mustache2 = _interopRequireDefault(_Mustache);
-
-function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
-
-const URL = 'https://stratum0.org/status/status.json';
-const TEMPLATES = {
-  template: _fs2.default.readFileSync('modules/brand/template.mustache', 'utf-8'),
-  status: _fs2.default.readFileSync('modules/brand/status.mustache', 'utf-8')
-};
-
-let status = {};
-
-function renderStatus(sock, everything) {
-  const sendInner = function () {
-    status.random = `${Math.random()}`;
-    sock.emit('brand.status', _Mustache2.default.render(TEMPLATES.status, status));
-  };
-  if (everything) {
-    sock.emit('brand', _Mustache2.default.render(TEMPLATES.template, {}));
-    setTimeout(sendInner, 3000);
-  } else {
-    sendInner();
-  }
-}
-
-function fetchStatus(cb) {
-  _httpreq2.default.get(URL, (err, res) => {
-    const state = JSON.parse(res.body).state;
-    cb(state);
-  });
-}
-
-module.exports = function (io) {
-  let firstTime = true;
-  function update() {
-    fetchStatus(state => {
-      if (status.lastchange !== state.lastchange) {
-        const d = new Date(state.lastchange * 1000);
-        state.since = `${DOW[d.getDay()]}, ${pad(d.getHours(), 2)}:${pad(d.getMinutes(), 2)}`;
-        status = state;
-        renderStatus(io);
-      }
-      if (firstTime && status) {
-        io.on('connection', sock => {
-          renderStatus(sock, true);
-        });
-        renderStatus(io, true);
-        firstTime = false;
-      } else {
-        renderStatus(io, false);
-      }
-    });
-  }
-  setInterval(update, 2 * 60 * 1000); //every 2 minutes
-  update();
-};
-//# sourceMappingURL=brand.js.map
\ No newline at end of file
diff --git a/modules/brand.js.map b/modules/brand.js.map
deleted file mode 100644
index 6d0e263b00ffb87792db5b62fa6ee462695ee3d8..0000000000000000000000000000000000000000
--- a/modules/brand.js.map
+++ /dev/null
@@ -1 +0,0 @@
-{"version":3,"sources":["../src/brand.js"],"names":["URL","TEMPLATES","template","readFileSync","status","renderStatus","sock","everything","sendInner","random","Math","emit","render","setTimeout","fetchStatus","cb","get","err","res","state","JSON","parse","body","module","exports","io","firstTime","update","lastchange","d","Date","since","DOW","getDay","pad","getHours","getMinutes","on","setInterval"],"mappings":";;AAAA;;;;AACA;;;;AACA;;;;;;AAEA,MAAMA,MAAM,yCAAZ;AACA,MAAMC,YAAY;AAChBC,YAAU,aAAGC,YAAH,CAAgB,iCAAhB,EAAmD,OAAnD,CADM;AAEhBC,UAAQ,aAAGD,YAAH,CAAgB,+BAAhB,EAAiD,OAAjD;AAFQ,CAAlB;;AAKA,IAAIC,SAAS,EAAb;;AAEA,SAASC,YAAT,CAAsBC,IAAtB,EAA4BC,UAA5B,EAAwC;AACtC,QAAMC,YAAY,YAAW;AAC3BJ,WAAOK,MAAP,GAAiB,GAAEC,KAAKD,MAAL,EAAc,EAAjC;AACAH,SAAKK,IAAL,CAAU,cAAV,EAA0B,mBAASC,MAAT,CAAgBX,UAAUG,MAA1B,EAAkCA,MAAlC,CAA1B;AACD,GAHD;AAIA,MAAIG,UAAJ,EAAgB;AACdD,SAAKK,IAAL,CAAU,OAAV,EAAmB,mBAASC,MAAT,CAAgBX,UAAUC,QAA1B,EAAoC,EAApC,CAAnB;AACAW,eAAWL,SAAX,EAAsB,IAAtB;AACD,GAHD,MAGO;AACLA;AACD;AACF;;AAED,SAASM,WAAT,CAAqBC,EAArB,EAAyB;AACvB,oBAAQC,GAAR,CAAYhB,GAAZ,EAAiB,CAACiB,GAAD,EAAMC,GAAN,KAAc;AAC7B,UAAMC,QAAQC,KAAKC,KAAL,CAAWH,IAAII,IAAf,EAAqBH,KAAnC;AACAJ,OAAGI,KAAH;AACD,GAHD;AAID;;AAEDI,OAAOC,OAAP,GAAiB,UAASC,EAAT,EAAa;AAC5B,MAAIC,YAAY,IAAhB;AACA,WAASC,MAAT,GAAkB;AAChBb,gBAAaK,KAAD,IAAW;AACrB,UAAIf,OAAOwB,UAAP,KAAsBT,MAAMS,UAAhC,EAA4C;AAC1C,cAAMC,IAAI,IAAIC,IAAJ,CAASX,MAAMS,UAAN,GAAmB,IAA5B,CAAV;AACAT,cAAMY,KAAN,GAAe,GAAEC,IAAIH,EAAEI,MAAF,EAAJ,CAAgB,KAAIC,IAAIL,EAAEM,QAAF,EAAJ,EAAkB,CAAlB,CAAqB,IAC1DD,IAAIL,EAAEO,UAAF,EAAJ,EAAoB,CAApB,CAAuB,EADvB;AAEAhC,iBAASe,KAAT;AACAd,qBAAaoB,EAAb;AACD;AACD,UAAIC,aAAatB,MAAjB,EAAyB;AACvBqB,WAAGY,EAAH,CAAM,YAAN,EAAqB/B,IAAD,IAAU;AAC5BD,uBAAaC,IAAb,EAAmB,IAAnB;AACD,SAFD;AAGAD,qBAAaoB,EAAb,EAAiB,IAAjB;AACAC,oBAAY,KAAZ;AACD,OAND,MAMO;AACLrB,qBAAaoB,EAAb,EAAiB,KAAjB;AACD;AACF,KAjBD;AAkBD;AACDa,cAAYX,MAAZ,EAAoB,IAAI,EAAJ,GAAS,IAA7B,EAtB4B,CAsBQ;AACpCA;AACD,CAxBD","file":"brand.js","sourcesContent":["import fs from 'fs';\nimport httpreq from 'httpreq';\nimport Mustache from 'Mustache';\n\nconst URL = 'https://stratum0.org/status/status.json';\nconst TEMPLATES = {\n  template: fs.readFileSync('modules/brand/template.mustache', 'utf-8'),\n  status: fs.readFileSync('modules/brand/status.mustache', 'utf-8'),\n};\n\nlet status = {};\n\nfunction renderStatus(sock, everything) {\n  const sendInner = function() {\n    status.random = `${Math.random()}`;\n    sock.emit('brand.status', Mustache.render(TEMPLATES.status, status));\n  };\n  if (everything) {\n    sock.emit('brand', Mustache.render(TEMPLATES.template, {}));\n    setTimeout(sendInner, 3000);\n  } else {\n    sendInner();\n  }\n}\n\nfunction fetchStatus(cb) {\n  httpreq.get(URL, (err, res) => {\n    const state = JSON.parse(res.body).state;\n    cb(state);\n  });\n}\n\nmodule.exports = function(io) {\n  let firstTime = true;\n  function update() {\n    fetchStatus((state) => {\n      if (status.lastchange !== state.lastchange) {\n        const d = new Date(state.lastchange * 1000);\n        state.since = `${DOW[d.getDay()]}, ${pad(d.getHours(), 2)}:${\n        pad(d.getMinutes(), 2)}`;\n        status = state;\n        renderStatus(io);\n      }\n      if (firstTime && status) {\n        io.on('connection', (sock) => {\n          renderStatus(sock, true);\n        });\n        renderStatus(io, true);\n        firstTime = false;\n      } else {\n        renderStatus(io, false);\n      }\n    });\n  }\n  setInterval(update, 2 * 60 * 1000); //every 2 minutes\n  update();\n};\n"]}
\ No newline at end of file
diff --git a/modules/brand/status.mustache b/modules/brand/status.mustache
deleted file mode 100644
index 06e7822936133e956b72ed202e431421bd6e9537..0000000000000000000000000000000000000000
--- a/modules/brand/status.mustache
+++ /dev/null
@@ -1,5 +0,0 @@
-Space is {{#open}}<span class="open">open</span> on <span class="person">{{trigger_person}}</span>{{/open}}
-{{^open}}<span class="closed">closed</span>{{/open}}
-<br>since {{since}}
-<br>
-<img style="width: 470px; height: 310px" src="http://maurudor.de/?rasd={{random}}"></img>
diff --git a/modules/brand/template.mustache b/modules/brand/template.mustache
deleted file mode 100644
index b2be527705a4bc92fd898c95c848ab1a00aae4db..0000000000000000000000000000000000000000
--- a/modules/brand/template.mustache
+++ /dev/null
@@ -1,2 +0,0 @@
-<img src="/modules/brand/stratum0_logo.svg"><br>
-<h3 data-infodisplay-outlet="status"></h3>
diff --git a/modules/bus.js b/modules/bus.js
deleted file mode 100644
index d51abbe04feef1450f69c85e0f65229f127bcf60..0000000000000000000000000000000000000000
--- a/modules/bus.js
+++ /dev/null
@@ -1,129 +0,0 @@
-'use strict';
-
-var _fs = require('fs');
-
-var _fs2 = _interopRequireDefault(_fs);
-
-var _httpreq = require('httpreq');
-
-var _httpreq2 = _interopRequireDefault(_httpreq);
-
-var _mustache = require('mustache');
-
-var _mustache2 = _interopRequireDefault(_mustache);
-
-var _pixlXml = require('pixl-xml');
-
-var _pixlXml2 = _interopRequireDefault(_pixlXml);
-
-function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
-
-/// CONFIG
-/* eslint no-mixed-operators: 0 */
-const CITY = 'Braunschweig';
-const STOPS = ['Ludwigstraße', 'Hamburger Straße'];
-const ENTRIES = 6;
-
-/// VARS
-let CACHED = [];
-const TEMPLATES = {
-  outer: _fs2.default.readFileSync('modules/bus/outer.mustache', 'utf-8'),
-  inner: _fs2.default.readFileSync('modules/bus/inner.mustache', 'utf-8')
-};
-
-function fetchData(stop, cb) {
-  const url = `http://62.154.206.87/efaws2/default/XML_DM_REQUEST?sessionID=0&requestID=0&language=de&useRealtime=1&coordOutputFormat=WGS84[DD.ddddd]&locationServerActive=1&mode=direct&dmLineSelectionAll=1&depType=STOPEVENTS&useAllStops=1&command=null&type_dm=stop&name_dm=${CITY} ${stop}&mId=efa_rc2`;
-  _httpreq2.default.get(url, { binary: true }, (err, res) => {
-    try {
-      cb(_pixlXml2.default.parse(res.body));
-    } catch (e) {
-      // Swallow
-    }
-  });
-}
-
-function renderLine(line) {
-  let image = '';
-  if (line.charAt(0) === 'M') {
-    image = 'metro.svg';
-    line = line.substr(1); // eslint-disable-line
-  } else if (line.length < 3) {
-    image = 'tram.svg';
-  } else {
-    image = 'bus.svg';
-  }
-  return `<img src="/modules/bus/${image}"> ${line}`;
-}
-
-function getData(stop, count, cb) {
-  fetchData(stop, data => {
-    const deps = data.itdDepartureMonitorRequest.itdDepartureList.itdDeparture;
-    cb(deps.slice(0, count).map(dep => ({
-      line: dep.itdServingLine.symbol,
-      renderedLine: renderLine(dep.itdServingLine.symbol),
-      dir: dep.itdServingLine.direction.replace(CITY, '').trim(),
-      platform: dep.platform,
-      mean: dep.itdServingLine.itdNoTrain.name,
-      day: pad(dep.itdDateTime.itdDate.day, 2),
-      month: pad(dep.itdDateTime.itdDate.month, 2),
-      hour: pad(dep.itdDateTime.itdTime.hour, 2),
-      minute: pad(dep.itdDateTime.itdTime.minute, 2)
-    })));
-  });
-}
-
-function update(io, allStopsDoneCb) {
-  const done = [];
-  const context = [];
-  const innerGetData = function (stop, i) {
-    const ns = normalizeStop(stop);
-    getData(stop, ENTRIES, deps => {
-      try {
-        context[i] = { stop, normalizedStop: ns, deps };
-        io.emit(`bus.${ns}`, _mustache2.default.render(TEMPLATES.inner, context[i]));
-        if (done.indexOf(stop) === -1) {
-          done.push(stop);
-          if (done.length === STOPS.length) {
-            allStopsDoneCb();
-          }
-        }
-        CACHED = context;
-      } catch (e) {
-        console.log(e); // eslint-disable-line
-      }
-      // calculate when to update next
-      const d = new Date();
-      const hour = d.getHours();
-      const minute = d.getMinutes();
-      const depHour = deps[0].hour < hour ? deps[0].hour + 24 : deps[0].hour;
-      const diff = (depHour - hour) * 60 + (deps[0].minute - minute);
-      setTimeout(() => {
-        innerGetData(stop, i);
-      }, (diff * 60 + (60 - d.getSeconds()) % 60) * 1000);
-    });
-  };
-  STOPS.forEach((stop, i) => {
-    innerGetData(stop, i);
-  });
-}
-
-function normalizeStop(stop) {
-  return stop.replace(/[^a-zA-Z0-9_]/g, '');
-}
-
-module.exports = function (io) {
-  update(io, () => {
-    const pushToClient = function (sock) {
-      sock.emit('bus', _mustache2.default.render(TEMPLATES.outer, CACHED));
-      setTimeout(() => {
-        for (const i in CACHED) {
-          // eslint-disable-line
-          sock.emit(`bus.${CACHED[i].normalizedStop}`, _mustache2.default.render(TEMPLATES.inner, CACHED[i]));
-        }
-      }, 3000); //wait a second to let the client process the outlets
-    };
-    io.on('connect', pushToClient);
-    pushToClient(io);
-  });
-};
-//# sourceMappingURL=bus.js.map
\ No newline at end of file
diff --git a/modules/bus.js.map b/modules/bus.js.map
deleted file mode 100644
index 233b48fa29c59cd6a6ab8284e87c89849a356bc5..0000000000000000000000000000000000000000
--- a/modules/bus.js.map
+++ /dev/null
@@ -1 +0,0 @@
-{"version":3,"sources":["../src/bus.js"],"names":["CITY","STOPS","ENTRIES","CACHED","TEMPLATES","outer","readFileSync","inner","fetchData","stop","cb","url","get","binary","err","res","parse","body","e","renderLine","line","image","charAt","substr","length","getData","count","data","deps","itdDepartureMonitorRequest","itdDepartureList","itdDeparture","slice","map","dep","itdServingLine","symbol","renderedLine","dir","direction","replace","trim","platform","mean","itdNoTrain","name","day","pad","itdDateTime","itdDate","month","hour","itdTime","minute","update","io","allStopsDoneCb","done","context","innerGetData","i","ns","normalizeStop","normalizedStop","emit","render","indexOf","push","console","log","d","Date","getHours","getMinutes","depHour","diff","setTimeout","getSeconds","forEach","module","exports","pushToClient","sock","on"],"mappings":"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","file":"bus.js","sourcesContent":["/* eslint no-mixed-operators: 0 */\nimport fs from 'fs';\nimport httpreq from 'httpreq';\nimport Mustache from 'mustache';\nimport XML from 'pixl-xml';\n\n/// CONFIG\nconst CITY = 'Braunschweig';\nconst STOPS = ['Ludwigstraße', 'Hamburger Straße'];\nconst ENTRIES = 6;\n\n/// VARS\nlet CACHED = [];\nconst TEMPLATES = {\n  outer: fs.readFileSync('modules/bus/outer.mustache', 'utf-8'),\n  inner: fs.readFileSync('modules/bus/inner.mustache', 'utf-8'),\n};\n\nfunction fetchData(stop, cb) {\n  const url = `http://62.154.206.87/efaws2/default/XML_DM_REQUEST?sessionID=0&requestID=0&language=de&useRealtime=1&coordOutputFormat=WGS84[DD.ddddd]&locationServerActive=1&mode=direct&dmLineSelectionAll=1&depType=STOPEVENTS&useAllStops=1&command=null&type_dm=stop&name_dm=${ CITY } ${ stop }&mId=efa_rc2`;\n  httpreq.get(url, { binary: true }, (err, res) => {\n    try {\n      cb(XML.parse(res.body));\n    } catch (e) {\n      // Swallow\n    }\n  });\n}\n\nfunction renderLine(line) {\n  let image = '';\n  if (line.charAt(0) === 'M') {\n    image = 'metro.svg';\n    line = line.substr(1); // eslint-disable-line\n  } else if (line.length < 3) {\n    image = 'tram.svg';\n  } else {\n    image = 'bus.svg';\n  }\n  return `<img src=\"/modules/bus/${image}\"> ${line}`;\n}\n\nfunction getData(stop, count, cb) {\n  fetchData(stop, (data) => {\n    const deps = data.itdDepartureMonitorRequest.itdDepartureList.itdDeparture;\n    cb(deps.slice(0, count).map((dep) => ({\n      line: dep.itdServingLine.symbol,\n      renderedLine: renderLine(dep.itdServingLine.symbol),\n      dir: dep.itdServingLine.direction.replace(CITY, '').trim(),\n      platform: dep.platform,\n      mean: dep.itdServingLine.itdNoTrain.name,\n      day: pad(dep.itdDateTime.itdDate.day, 2),\n      month: pad(dep.itdDateTime.itdDate.month, 2),\n      hour: pad(dep.itdDateTime.itdTime.hour, 2),\n      minute: pad(dep.itdDateTime.itdTime.minute, 2),\n    })));\n  });\n}\n\nfunction update(io, allStopsDoneCb) {\n  const done = [];\n  const context = [];\n  const innerGetData = function(stop, i) {\n    const ns = normalizeStop(stop);\n    getData(stop, ENTRIES, (deps) => {\n      try {\n        context[i] = { stop, normalizedStop: ns, deps };\n        io.emit(`bus.${ns}`, Mustache.render(TEMPLATES.inner, context[i]));\n        if (done.indexOf(stop) === -1) {\n          done.push(stop);\n          if (done.length === STOPS.length) {\n            allStopsDoneCb();\n          }\n        }\n        CACHED = context;\n      } catch (e) {\n        console.log(e); // eslint-disable-line\n      }\n      // calculate when to update next\n      const d = new Date();\n      const hour = d.getHours();\n      const minute = d.getMinutes();\n      const depHour = deps[0].hour < hour ? deps[0].hour + 24 : deps[0].hour;\n      const diff = (depHour - hour) * 60 + (deps[0].minute - minute);\n      setTimeout(() => {\n        innerGetData(stop, i);\n      }, (diff * 60 + (60 - d.getSeconds()) % 60) * 1000);\n    });\n  };\n  STOPS.forEach((stop, i) => {\n    innerGetData(stop, i);\n  });\n}\n\nfunction normalizeStop(stop) {\n  return stop.replace(/[^a-zA-Z0-9_]/g, '');\n}\n\nmodule.exports = function(io) {\n  update(io, () => {\n    const pushToClient = function(sock) {\n      sock.emit('bus', Mustache.render(TEMPLATES.outer, CACHED));\n      setTimeout(() => {\n        for (const i in CACHED) { // eslint-disable-line\n          sock.emit(`bus.${CACHED[i].normalizedStop}`,\n            Mustache.render(TEMPLATES.inner, CACHED[i]));\n          }\n        }, 3000); //wait a second to let the client process the outlets\n      };\n      io.on('connect', pushToClient);\n      pushToClient(io);\n    });\n  };\n"]}
\ No newline at end of file
diff --git a/modules/bus/inner.mustache b/modules/bus/inner.mustache
deleted file mode 100644
index 2c30bc3e70ccc7649f4d1df25ba70f2a828325d7..0000000000000000000000000000000000000000
--- a/modules/bus/inner.mustache
+++ /dev/null
@@ -1,22 +0,0 @@
-<tr>
-    <th class="title" colspan="4">
-        <h3><img src="/modules/bus/bsv.svg"> {{stop}}</h3>
-    </th>
-</tr>
-<tr>
-    <th>Time</th>
-    <th>Line</th>
-    <th>Pltf</th>
-    <th>Direction</th>
-</tr>
-{{#deps}}
-    <tr>
-        <td class="time">
-            <span>{{hour}}:{{minute}}</span>
-            (<font class="until"></font>)
-        </td>
-        <td>{{{renderedLine}}}</td>
-        <td>{{platform}}</td>
-        <td>{{dir}}</td>
-    </tr>
-{{/deps}}
diff --git a/modules/bus/outer.mustache b/modules/bus/outer.mustache
deleted file mode 100644
index 7f60d24ee06685506288890e61107749e8b34a0b..0000000000000000000000000000000000000000
--- a/modules/bus/outer.mustache
+++ /dev/null
@@ -1,13 +0,0 @@
-<link rel="stylesheet" href="/modules/bus/bus.css">
-<script type="text/javascript" src="/modules/bus/bus.js"></script>
-<table id="busTable">
-    <colgroup>
-        <col width="140px">
-        <col width="80px">
-        <col>
-        <col>
-    </colgroup>
-    {{#.}}
-        <tbody data-infodisplay-outlet="{{normalizedStop}}"></tbody>
-    {{/.}}
-</table>
diff --git a/modules/calendar.js b/modules/calendar.js
deleted file mode 100644
index 61bdba050373c71e3a15d192eff3ba140ce0a2d6..0000000000000000000000000000000000000000
--- a/modules/calendar.js
+++ /dev/null
@@ -1,125 +0,0 @@
-'use strict';
-
-var _fs = require('fs');
-
-var _fs2 = _interopRequireDefault(_fs);
-
-var _httpreq = require('httpreq');
-
-var _httpreq2 = _interopRequireDefault(_httpreq);
-
-var _ical = require('ical.js');
-
-var _ical2 = _interopRequireDefault(_ical);
-
-var _mustache = require('mustache');
-
-var _mustache2 = _interopRequireDefault(_mustache);
-
-var _time = require('time');
-
-var _time2 = _interopRequireDefault(_time);
-
-function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
-
-const URL = 'https://stratum0.org/kalender/termine.ics'; /* eslint no-mixed-operators: 0 */
-
-const TEMPLATE = _fs2.default.readFileSync('modules/calendar/template.mustache', 'utf-8');
-let CALENDAR;
-
-const TZOFFSET = new _time2.default.Date().getTimezoneOffset() * 60;
-
-function getData(count, cb) {
-  _httpreq2.default.get(URL, (err, res) => {
-    const ics = res.body.replace(/[0-9]{8}T[0-9]{6}/g, '$&Z');
-    const cal = new _ical2.default.Component(_ical2.default.parse(ics));
-    const rawEvents = cal.getAllSubcomponents('vevent').map(raw => new _ical2.default.Event(raw));
-    const events = [];
-    const p = function (p) {
-      return ev.component.getFirstPropertyValue(p);
-    };
-    let ev = p;
-    for (const i in rawEvents) {
-      // eslint-disable-line
-      ev = rawEvents[i];
-      if (ev.isRecurring()) {
-        const iter = ev.iterator();
-        const duration = p('dtend').toUnixTime() - p('dtstart').toUnixTime();
-        for (let i = 0; i < 100; i++) {
-          const next = iter.next();
-          if (next === undefined) {
-            break;
-          }
-          const start = next.toUnixTime() + TZOFFSET;
-          events.push({
-            title: p('summary'),
-            start,
-            end: start + duration
-          });
-        }
-      } else {
-        events.push({
-          title: p('summary'),
-          start: p('dtstart').toUnixTime() + TZOFFSET,
-          end: p('dtend').toUnixTime() + TZOFFSET
-        });
-      }
-    }
-    events.sort((a, b) => a.start - b.start);
-    const threshold = Date.now() / 1000 - 5 * 60 * 60; //show 5 hours ago
-    let i;
-    for (i in events) {
-      if (events[i].end > threshold) {
-        i = parseInt(i, 10);
-        break;
-      }
-    }
-    const now = new Date();
-    cb(events.slice(i, i + count).map(ev => {
-      const start = new Date(ev.start * 1000);
-      if (start.getMonth() === now.getMonth() && start.getDate() === now.getDate()) {
-        ev.startRendered = `${pad(start.getHours(), 2)}:${pad(start.getMinutes(), 2)}`;
-      } else {
-        ev.startRendered = `${DOW[start.getDay()]}, ${pad(start.getDate(), 2)}.${pad(start.getMonth() + 1, 2)}. ${pad(start.getHours(), 2)}:${pad(start.getMinutes(), 2)}`;
-      }
-      const end = new Date(ev.end * 1000);
-      if (ev.end - ev.start >= 60 * 60 * 24) {
-        ev.endRendered = `${DOW[end.getDay()]} ${pad(end.getHours(), 2)}:${pad(end.getMinutes(), 2)}`;
-      } else {
-        ev.endRendered = `${pad(end.getHours(), 2)}:${pad(end.getMinutes(), 2)}`;
-      }
-      const dur = Math.floor((ev.end - ev.start) / 60);
-      ev.duration = `${pad(Math.floor(dur / 60), 2)}:${pad(dur % 60, 2)}`;
-      if (start.getTime() < now.getTime()) {
-        if (end.getTime() < now.getTime()) {
-          ev.past = true;
-        } else {
-          ev.now = true;
-        }
-      }
-      return ev;
-    }));
-  });
-}
-
-module.exports = function (io) {
-  function update(firstRunCallback) {
-    getData(8, data => {
-      CALENDAR = data;
-      io.emit('calendar', _mustache2.default.render(TEMPLATE, CALENDAR));
-      if (firstRunCallback) {
-        firstRunCallback();
-        firstRunCallback = null; // eslint-disable-line
-      }
-    });
-  }
-  update(() => {
-    const pushToClients = function (sock) {
-      sock.emit('calendar', _mustache2.default.render(TEMPLATE, CALENDAR));
-    };
-    io.on('connect', pushToClients);
-    pushToClients(io);
-  });
-  setInterval(update, 600000);
-};
-//# sourceMappingURL=calendar.js.map
\ No newline at end of file
diff --git a/modules/calendar.js.map b/modules/calendar.js.map
deleted file mode 100644
index 86a8161dc992a5349a2c813588b1bbbab62820a0..0000000000000000000000000000000000000000
--- a/modules/calendar.js.map
+++ /dev/null
@@ -1 +0,0 @@
-{"version":3,"sources":["../src/calendar.js"],"names":["URL","TEMPLATE","readFileSync","CALENDAR","TZOFFSET","Date","getTimezoneOffset","getData","count","cb","get","err","res","ics","body","replace","cal","Component","parse","rawEvents","getAllSubcomponents","map","raw","Event","events","p","ev","component","getFirstPropertyValue","i","isRecurring","iter","iterator","duration","toUnixTime","next","undefined","start","push","title","end","sort","a","b","threshold","now","parseInt","slice","getMonth","getDate","startRendered","pad","getHours","getMinutes","DOW","getDay","endRendered","dur","Math","floor","getTime","past","module","exports","io","update","firstRunCallback","data","emit","render","pushToClients","sock","on","setInterval"],"mappings":"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","file":"calendar.js","sourcesContent":["/* eslint no-mixed-operators: 0 */\nimport fs from 'fs';\nimport httpreq from 'httpreq';\nimport ical from 'ical.js';\nimport Mustache from 'mustache';\nimport time from 'time';\n\nconst URL = 'https://stratum0.org/kalender/termine.ics';\nconst TEMPLATE = fs.readFileSync('modules/calendar/template.mustache', 'utf-8');\nlet CALENDAR;\n\nconst TZOFFSET = new time.Date().getTimezoneOffset() * 60;\n\n\nfunction getData(count, cb) {\n  httpreq.get(URL, (err, res) => {\n    const ics = res.body.replace(/[0-9]{8}T[0-9]{6}/g, '$&Z');\n    const cal = new ical.Component(ical.parse(ics));\n    const rawEvents = cal.getAllSubcomponents('vevent').map((raw) => new ical.Event(raw));\n    const events = [];\n    const p = function(p) {\n      return ev.component.getFirstPropertyValue(p);\n    };\n    let ev = p;\n    for (const i in rawEvents) { // eslint-disable-line\n      ev = rawEvents[i];\n      if (ev.isRecurring()) {\n        const iter = ev.iterator();\n        const duration = p('dtend').toUnixTime() - p('dtstart').toUnixTime();\n        for (let i = 0; i < 100; i++) {\n          const next = iter.next();\n          if (next === undefined) {\n            break;\n          }\n          const start = next.toUnixTime() + TZOFFSET;\n          events.push({\n            title: p('summary'),\n            start,\n            end: start + duration,\n          });\n        }\n      } else {\n        events.push({\n          title: p('summary'),\n          start: p('dtstart').toUnixTime() + TZOFFSET,\n          end: p('dtend').toUnixTime() + TZOFFSET,\n        });\n      }\n    }\n    events.sort((a, b) => a.start - b.start);\n    const threshold = Date.now() / 1000 - 5 * 60 * 60; //show 5 hours ago\n    let i;\n    for (i in events) {\n      if (events[i].end > threshold) {\n        i = parseInt(i, 10);\n        break;\n      }\n    }\n    const now = new Date();\n    cb(events.slice(i, i + count).map((ev) => {\n      const start = new Date(ev.start * 1000);\n      if (start.getMonth() === now.getMonth() && start.getDate() === now.getDate()) {\n        ev.startRendered = `${pad(start.getHours(), 2)}:${pad(start.getMinutes(), 2)}`;\n      } else {\n        ev.startRendered = `${DOW[start.getDay()]}, ${pad(start.getDate(), 2)\n        }.${pad(start.getMonth() + 1, 2)}. ${pad(start.getHours(), 2)\n        }:${pad(start.getMinutes(), 2)}`;\n      }\n      const end = new Date(ev.end * 1000);\n      if (ev.end - ev.start >= 60 * 60 * 24) {\n        ev.endRendered = `${DOW[end.getDay()]} ${pad(end.getHours(), 2)\n        }:${pad(end.getMinutes(), 2)}`;\n      } else {\n        ev.endRendered = `${pad(end.getHours(), 2)}:${pad(end.getMinutes(), 2)}`;\n      }\n      const dur = Math.floor((ev.end - ev.start) / 60);\n      ev.duration = `${pad(Math.floor(dur / 60), 2) }:${ pad((dur % 60), 2)}`;\n      if (start.getTime() < now.getTime()) {\n        if (end.getTime() < now.getTime()) {\n          ev.past = true;\n        } else {\n          ev.now = true;\n        }\n      }\n      return ev;\n    }));\n  });\n}\n\nmodule.exports = function(io) {\n  function update(firstRunCallback) {\n    getData(8, (data) => {\n      CALENDAR = data;\n      io.emit('calendar', Mustache.render(TEMPLATE, CALENDAR));\n      if (firstRunCallback) {\n        firstRunCallback();\n        firstRunCallback = null; // eslint-disable-line\n      }\n    });\n  }\n  update(() => {\n    const pushToClients = function(sock) {\n      sock.emit('calendar', Mustache.render(TEMPLATE, CALENDAR));\n    };\n    io.on('connect', pushToClients);\n    pushToClients(io);\n  });\n  setInterval(update, 600000);\n};\n"]}
\ No newline at end of file
diff --git a/modules/calendar/template.mustache b/modules/calendar/template.mustache
deleted file mode 100644
index e5561b2d39128e12ff723bce0f2767092677814a..0000000000000000000000000000000000000000
--- a/modules/calendar/template.mustache
+++ /dev/null
@@ -1,9 +0,0 @@
-<h3>Next Events</h3>
-{{#.}}
-{{#now}}<font color="#2aa198">{{/now}}
-{{#past}}<font color="#586e75">{{/past}}
-    <b>{{title}}{{#now}} (now){{/now}}{{#past}} (over){{/past}}</b><br>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;from {{startRendered}} until {{endRendered}} ({{duration}} h)<br>
-{{#past}}</font>{{/past}}
-{{#now}}</font>{{/now}}
-{{/.}}
diff --git a/modules/date.js b/modules/date.js
deleted file mode 100644
index e2ed2db3578968761a2e0e8c5ddbbf11d67c422b..0000000000000000000000000000000000000000
--- a/modules/date.js
+++ /dev/null
@@ -1,13 +0,0 @@
-'use strict';
-
-function date() {
-  const d = new Date();
-  return `${DOW[d.getDay()]}, ${pad(d.getDate(), 2)}.${pad(d.getMonth() + 1, 2)}.${d.getFullYear()} ${pad(d.getHours(), 2)}:${pad(d.getMinutes(), 2)}:${pad(d.getSeconds(), 2)}`;
-}
-
-module.exports = function (io) {
-  setInterval(() => {
-    io.emit('date', `<div align="right"><h2>${date()}&nbsp;</h2></div>`);
-  }, 1000);
-};
-//# sourceMappingURL=date.js.map
\ No newline at end of file
diff --git a/modules/date.js.map b/modules/date.js.map
deleted file mode 100644
index dc0542f976e5867382085af1b36a8188d836b9f8..0000000000000000000000000000000000000000
--- a/modules/date.js.map
+++ /dev/null
@@ -1 +0,0 @@
-{"version":3,"sources":["../src/date.js"],"names":["date","d","Date","DOW","getDay","pad","getDate","getMonth","getFullYear","getHours","getMinutes","getSeconds","module","exports","io","setInterval","emit"],"mappings":";;AAAA,SAASA,IAAT,GAAgB;AACd,QAAMC,IAAI,IAAIC,IAAJ,EAAV;AACA,SAAQ,GAAEC,IAAIF,EAAEG,MAAF,EAAJ,CAAgB,KAAIC,IAAIJ,EAAEK,OAAF,EAAJ,EAAiB,CAAjB,CAAoB,IAAGD,IAAIJ,EAAEM,QAAF,KAAe,CAAnB,EAAsB,CAAtB,CAAyB,IAAGN,EAAEO,WAAF,EAAgB,IAAGH,IAAIJ,EAAEQ,QAAF,EAAJ,EAAkB,CAAlB,CAAqB,IAAGJ,IAAIJ,EAAES,UAAF,EAAJ,EAAoB,CAApB,CAAuB,IAAGL,IAAIJ,EAAEU,UAAF,EAAJ,EAAoB,CAApB,CAAuB,EAA7K;AACD;;AAGDC,OAAOC,OAAP,GAAiB,UAASC,EAAT,EAAa;AAC5BC,cAAY,MAAM;AAChBD,OAAGE,IAAH,CAAQ,MAAR,EAAiB,0BAAyBhB,MAAO,mBAAjD;AACD,GAFD,EAEG,IAFH;AAGD,CAJD","file":"date.js","sourcesContent":["function date() {\n  const d = new Date();\n  return `${DOW[d.getDay()]}, ${pad(d.getDate(), 2)}.${pad(d.getMonth() + 1, 2)}.${d.getFullYear()} ${pad(d.getHours(), 2)}:${pad(d.getMinutes(), 2)}:${pad(d.getSeconds(), 2)}`;\n}\n\n\nmodule.exports = function(io) {\n  setInterval(() => {\n    io.emit('date', `<div align=\"right\"><h2>${date()}&nbsp;</h2></div>`);\n  }, 1000);\n};\n"]}
\ No newline at end of file
diff --git a/modules/diagrams.js b/modules/diagrams.js
deleted file mode 100644
index 0f3460cdf68a43327af42e7596a536e1c36fdac5..0000000000000000000000000000000000000000
--- a/modules/diagrams.js
+++ /dev/null
@@ -1,75 +0,0 @@
-'use strict';
-
-var _fs = require('fs');
-
-var _fs2 = _interopRequireDefault(_fs);
-
-var _httpreq = require('httpreq');
-
-var _httpreq2 = _interopRequireDefault(_httpreq);
-
-var _mustache = require('mustache');
-
-var _mustache2 = _interopRequireDefault(_mustache);
-
-function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
-
-const TEMPLATES = {
-  main: _fs2.default.readFileSync('modules/diagrams/main.mustache', 'utf-8'),
-  data: _fs2.default.readFileSync('modules/diagrams/data.mustache', 'utf-8')
-};
-
-function fetchData(id, cb) {
-  const url = `http://shiny.tinyhost.de/php/getdata.php?time=1&id[]=${id}`;
-  _httpreq2.default.get(url, { binary: true }, (err, res) => {
-    try {
-      cb(res.body.toString().split('\n'));
-    } catch (e) {
-      // Swallow Error
-    }
-  });
-}
-
-const DATA = { power: '[]', devices: '[]' };
-
-function handleData(prop, data) {
-  let line = [];
-  const out = [];
-  for (let i = 1; i < data.length - 1; i++) {
-    line = data[i].split(',');
-    if (line.length === 2) {
-      out.push([new Date(line[0]).getTime(), parseFloat(line[1])]);
-    }
-  }
-  DATA[prop] = JSON.stringify(out);
-}
-
-function update(cb) {
-  let counter = 0;
-  const next = function () {
-    counter += 1;
-    if (counter === 2) {
-      cb();
-    }
-  };
-  fetchData(1, data => {
-    handleData('power', data);
-    next();
-  }); //power
-  fetchData(4, data => {
-    handleData('devices', data);
-    next();
-  }); //devices
-}
-
-module.exports = function (io) {
-  setInterval(() => {
-    update(() => {
-      io.emit('diagrams.data', _mustache2.default.render(TEMPLATES.data, DATA));
-    });
-  }, 5000);
-  io.on('connect', sock => {
-    sock.emit('diagrams', _mustache2.default.render(TEMPLATES.main, {}));
-  });
-};
-//# sourceMappingURL=diagrams.js.map
\ No newline at end of file
diff --git a/modules/diagrams.js.map b/modules/diagrams.js.map
deleted file mode 100644
index 8a6e0723be672404d6051e93d414b91db8ede456..0000000000000000000000000000000000000000
--- a/modules/diagrams.js.map
+++ /dev/null
@@ -1 +0,0 @@
-{"version":3,"sources":["../src/diagrams.js"],"names":["TEMPLATES","main","readFileSync","data","fetchData","id","cb","url","get","binary","err","res","body","toString","split","e","DATA","power","devices","handleData","prop","line","out","i","length","push","Date","getTime","parseFloat","JSON","stringify","update","counter","next","module","exports","io","setInterval","emit","render","on","sock"],"mappings":";;AAAA;;;;AACA;;;;AACA;;;;;;AAEA,MAAMA,YAAY;AAChBC,QAAM,aAAGC,YAAH,CAAgB,gCAAhB,EAAkD,OAAlD,CADU;AAEhBC,QAAM,aAAGD,YAAH,CAAgB,gCAAhB,EAAkD,OAAlD;AAFU,CAAlB;;AAKA,SAASE,SAAT,CAAmBC,EAAnB,EAAuBC,EAAvB,EAA2B;AACzB,QAAMC,MAAO,wDAAuDF,EAAG,EAAvE;AACA,oBAAQG,GAAR,CAAYD,GAAZ,EAAiB,EAAEE,QAAQ,IAAV,EAAjB,EAAmC,CAACC,GAAD,EAAMC,GAAN,KAAc;AAC/C,QAAI;AACFL,SAAGK,IAAIC,IAAJ,CAASC,QAAT,GAAoBC,KAApB,CAA0B,IAA1B,CAAH;AACD,KAFD,CAEE,OAAOC,CAAP,EAAU;AACV;AACD;AACF,GAND;AAOD;;AAED,MAAMC,OAAO,EAAEC,OAAO,IAAT,EAAeC,SAAS,IAAxB,EAAb;;AAEA,SAASC,UAAT,CAAoBC,IAApB,EAA0BjB,IAA1B,EAAgC;AAC9B,MAAIkB,OAAO,EAAX;AACA,QAAMC,MAAM,EAAZ;AACA,OAAK,IAAIC,IAAI,CAAb,EAAgBA,IAAIpB,KAAKqB,MAAL,GAAc,CAAlC,EAAqCD,GAArC,EAA0C;AACxCF,WAAOlB,KAAKoB,CAAL,EAAQT,KAAR,CAAc,GAAd,CAAP;AACA,QAAIO,KAAKG,MAAL,KAAgB,CAApB,EAAuB;AACrBF,UAAIG,IAAJ,CAAS,CAAE,IAAIC,IAAJ,CAASL,KAAK,CAAL,CAAT,CAAD,CAAoBM,OAApB,EAAD,EAAgCC,WAAWP,KAAK,CAAL,CAAX,CAAhC,CAAT;AACD;AACF;AACDL,OAAKI,IAAL,IAAaS,KAAKC,SAAL,CAAeR,GAAf,CAAb;AACD;;AAED,SAASS,MAAT,CAAgBzB,EAAhB,EAAoB;AAClB,MAAI0B,UAAU,CAAd;AACA,QAAMC,OAAO,YAAW;AACtBD,eAAW,CAAX;AACA,QAAIA,YAAY,CAAhB,EAAmB;AACjB1B;AACD;AACF,GALD;AAMAF,YAAU,CAAV,EAAcD,IAAD,IAAU;AACrBgB,eAAW,OAAX,EAAoBhB,IAApB;AACA8B;AACD,GAHD,EARkB,CAWd;AACJ7B,YAAU,CAAV,EAAcD,IAAD,IAAU;AACrBgB,eAAW,SAAX,EAAsBhB,IAAtB;AACA8B;AACD,GAHD,EAZkB,CAed;AACL;;AAEDC,OAAOC,OAAP,GAAiB,UAASC,EAAT,EAAa;AAC5BC,cAAY,MAAM;AAChBN,WAAO,MAAM;AACXK,SAAGE,IAAH,CAAQ,eAAR,EAAyB,mBAASC,MAAT,CAAgBvC,UAAUG,IAA1B,EAAgCa,IAAhC,CAAzB;AACD,KAFD;AAGD,GAJD,EAIG,IAJH;AAKAoB,KAAGI,EAAH,CAAM,SAAN,EAAkBC,IAAD,IAAU;AACzBA,SAAKH,IAAL,CAAU,UAAV,EAAsB,mBAASC,MAAT,CAAgBvC,UAAUC,IAA1B,EAAgC,EAAhC,CAAtB;AACD,GAFD;AAGD,CATD","file":"diagrams.js","sourcesContent":["import fs from 'fs';\nimport httpreq from 'httpreq';\nimport Mustache from 'mustache';\n\nconst TEMPLATES = {\n  main: fs.readFileSync('modules/diagrams/main.mustache', 'utf-8'),\n  data: fs.readFileSync('modules/diagrams/data.mustache', 'utf-8'),\n};\n\nfunction fetchData(id, cb) {\n  const url = `http://shiny.tinyhost.de/php/getdata.php?time=1&id[]=${id}`;\n  httpreq.get(url, { binary: true }, (err, res) => {\n    try {\n      cb(res.body.toString().split('\\n'));\n    } catch (e) {\n      // Swallow Error\n    }\n  });\n}\n\nconst DATA = { power: '[]', devices: '[]' };\n\nfunction handleData(prop, data) {\n  let line = [];\n  const out = [];\n  for (let i = 1; i < data.length - 1; i++) {\n    line = data[i].split(',');\n    if (line.length === 2) {\n      out.push([(new Date(line[0])).getTime(), parseFloat(line[1])]);\n    }\n  }\n  DATA[prop] = JSON.stringify(out);\n}\n\nfunction update(cb) {\n  let counter = 0;\n  const next = function() {\n    counter += 1;\n    if (counter === 2) {\n      cb();\n    }\n  };\n  fetchData(1, (data) => {\n    handleData('power', data);\n    next();\n  }); //power\n  fetchData(4, (data) => {\n    handleData('devices', data);\n    next();\n  }); //devices\n}\n\nmodule.exports = function(io) {\n  setInterval(() => {\n    update(() => {\n      io.emit('diagrams.data', Mustache.render(TEMPLATES.data, DATA));\n    });\n  }, 5000);\n  io.on('connect', (sock) => {\n    sock.emit('diagrams', Mustache.render(TEMPLATES.main, {}));\n  });\n};\n"]}
\ No newline at end of file
diff --git a/modules/diagrams/data.mustache b/modules/diagrams/data.mustache
deleted file mode 100644
index 187dc8672988ceb6bbc95a49d99f3ec0db4e76b9..0000000000000000000000000000000000000000
--- a/modules/diagrams/data.mustache
+++ /dev/null
@@ -1,16 +0,0 @@
-<script>
-var power = {{power}};
-var devices = {{devices}};
-$.plot("#diagrams-container", [
-    { data: power, label: "Power consumption (W)", color: '#b58900' },
-    { data: devices, label: "Network devices", yaxis: 2, color: '#268bd2' }
-], {
-    xaxes: [ { mode: "time" } ],
-    yaxes: [ { min: 0 }, {
-        alignTicksWithAxis: 0,
-        position: 'right',
-        min: 0
-    } ],
-    legend: { position: "sw", backgroundColor: '#eee8d5' }
-});
-</script>
diff --git a/modules/diagrams/main.mustache b/modules/diagrams/main.mustache
deleted file mode 100644
index 77960bb17991b382eee3bd97653197b2dbc2f053..0000000000000000000000000000000000000000
--- a/modules/diagrams/main.mustache
+++ /dev/null
@@ -1,3 +0,0 @@
-<h3>Power consumption<span style="float: right">Network devices&nbsp;&nbsp;</span></h3>
-<span style="display: none" data-infodisplay-outlet="data"></span>
-<div id="diagrams-container" style="height: 90%; width: 96%"></div>
diff --git a/modules/irc.js b/modules/irc.js
deleted file mode 100644
index 5c8c43ec05609de811262e9b2af95717cddd9240..0000000000000000000000000000000000000000
--- a/modules/irc.js
+++ /dev/null
@@ -1,42 +0,0 @@
-'use strict';
-
-var _irc = require('irc');
-
-var _irc2 = _interopRequireDefault(_irc);
-
-function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
-
-const CHANNEL = '#stratum0';
-
-const PW = 'Fagee9ie';
-
-module.exports = function (io) {
-  const client = new _irc2.default.Client('bouncer.ksal.de', 'infodisplay', {
-    channels: [CHANNEL],
-    port: 28921,
-    secure: true,
-    selfSigned: true,
-    userName: 'infodisplay/Freenode',
-    password: PW
-  });
-  const content = [];
-  client.addListener('message', (from, to, message) => {
-    if (to !== CHANNEL || from === undefined) {
-      return;
-    }
-    // eslint-disable-next-line
-    message = message.replace(/</g, '&lt;').replace(/>/g, '&gt;');
-    content.push(`<p><span>${from}</span> ${message}</p>`);
-    if (content.length > 25) {
-      content.shift();
-    }
-    io.emit('irc.inner', content.join(''));
-  });
-  io.on('connect', sock => {
-    sock.emit('irc', '<h3>&nbsp;IRC #stratum0</h3><div class="chat" data-infodisplay-outlet="inner"></div>');
-    setTimeout(() => {
-      sock.emit('irc.inner', content.join(''));
-    }, 3000);
-  });
-};
-//# sourceMappingURL=irc.js.map
\ No newline at end of file
diff --git a/modules/irc.js.map b/modules/irc.js.map
deleted file mode 100644
index 4a460493bc659c4a1996e979c9752df9690d775c..0000000000000000000000000000000000000000
--- a/modules/irc.js.map
+++ /dev/null
@@ -1 +0,0 @@
-{"version":3,"sources":["../src/irc.js"],"names":["CHANNEL","PW","module","exports","io","client","Client","channels","port","secure","selfSigned","userName","password","content","addListener","from","to","message","undefined","replace","push","length","shift","emit","join","on","sock","setTimeout"],"mappings":";;AAAA;;;;;;AAEA,MAAMA,UAAU,WAAhB;;AAEA,MAAMC,KAAK,UAAX;;AAEAC,OAAOC,OAAP,GAAiB,UAASC,EAAT,EAAa;AAC5B,QAAMC,SAAS,IAAI,cAAIC,MAAR,CAAe,iBAAf,EAAkC,aAAlC,EAAiD;AAC9DC,cAAU,CAACP,OAAD,CADoD;AAE9DQ,UAAM,KAFwD;AAG9DC,YAAQ,IAHsD;AAI9DC,gBAAY,IAJkD;AAK9DC,cAAU,sBALoD;AAM9DC,cAAUX;AANoD,GAAjD,CAAf;AAQA,QAAMY,UAAU,EAAhB;AACAR,SAAOS,WAAP,CAAmB,SAAnB,EAA8B,CAACC,IAAD,EAAOC,EAAP,EAAWC,OAAX,KAAuB;AACnD,QAAID,OAAOhB,OAAP,IAAkBe,SAASG,SAA/B,EAA0C;AACxC;AACD;AACD;AACAD,cAAUA,QAAQE,OAAR,CAAgB,IAAhB,EAAsB,MAAtB,EAA8BA,OAA9B,CAAsC,IAAtC,EAA4C,MAA5C,CAAV;AACAN,YAAQO,IAAR,CAAc,YAAWL,IAAK,WAAUE,OAAQ,MAAhD;AACA,QAAIJ,QAAQQ,MAAR,GAAiB,EAArB,EAAyB;AACvBR,cAAQS,KAAR;AACD;AACDlB,OAAGmB,IAAH,CAAQ,WAAR,EAAqBV,QAAQW,IAAR,CAAa,EAAb,CAArB;AACD,GAXD;AAYApB,KAAGqB,EAAH,CAAM,SAAN,EAAiBC,QAAQ;AACvBA,SAAKH,IAAL,CACE,KADF,EAEE,sFAFF;AAIAI,eACE,MAAM;AACJD,WAAKH,IAAL,CAAU,WAAV,EAAuBV,QAAQW,IAAR,CAAa,EAAb,CAAvB;AACD,KAHH,EAIE,IAJF;AAMD,GAXD;AAYD,CAlCD","file":"irc.js","sourcesContent":["import irc from 'irc';\n\nconst CHANNEL = '#stratum0';\n\nconst PW = 'Fagee9ie';\n\nmodule.exports = function(io) {\n  const client = new irc.Client('bouncer.ksal.de', 'infodisplay', {\n    channels: [CHANNEL],\n    port: 28921,\n    secure: true,\n    selfSigned: true,\n    userName: 'infodisplay/Freenode',\n    password: PW,\n  });\n  const content = [];\n  client.addListener('message', (from, to, message) => {\n    if (to !== CHANNEL || from === undefined) {\n      return;\n    }\n    // eslint-disable-next-line\n    message = message.replace(/</g, '&lt;').replace(/>/g, '&gt;');\n    content.push(`<p><span>${from}</span> ${message}</p>`);\n    if (content.length > 25) {\n      content.shift();\n    }\n    io.emit('irc.inner', content.join(''));\n  });\n  io.on('connect', sock => {\n    sock.emit(\n      'irc',\n      '<h3>&nbsp;IRC #stratum0</h3><div class=\"chat\" data-infodisplay-outlet=\"inner\"></div>'\n    );\n    setTimeout(\n      () => {\n        sock.emit('irc.inner', content.join(''));\n      },\n      3000\n    );\n  });\n};\n"]}
\ No newline at end of file
diff --git a/modules/weather.js b/modules/weather.js
deleted file mode 100644
index a5d6af08f4014b2dbb9c4c97673dc38b21173465..0000000000000000000000000000000000000000
--- a/modules/weather.js
+++ /dev/null
@@ -1,103 +0,0 @@
-'use strict';
-
-var _fs = require('fs');
-
-var _fs2 = _interopRequireDefault(_fs);
-
-var _httpreq = require('httpreq');
-
-var _httpreq2 = _interopRequireDefault(_httpreq);
-
-var _mustache = require('mustache');
-
-var _mustache2 = _interopRequireDefault(_mustache);
-
-function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
-
-///CONFIG
-const APPID = 'fdc3690e6f9a7572128fe4012b4a2500';
-const CITYID = '2945024';
-
-/// STATICS
-const directions = { NNE: 11.25, NE: 33.75, ENE: 56.25, E: 78.75, ESE: 101.25, SE: 123.75, SSE: 146.25, S: 168.75, SSW: 191.25, SW: 213.75, WSW: 236.25, W: 258.75, WNW: 281.25, NW: 303.75, NNW: 326.25, N: 348.75 };
-const iconBaseURL = 'http://openweathermap.org/img/w/';
-const TEMPLATE = _fs2.default.readFileSync('modules/weather/template.mustache', 'utf-8');
-
-function fetchCurrent(cityid, cb) {
-  const url = `http://api.openweathermap.org/data/2.5/weather?units=metric&id=${cityid}&appid=${APPID}`;
-  _httpreq2.default.get(url, (err, res) => {
-    const dat = JSON.parse(res.body);
-    if (dat.cod) {
-      cb({
-        temp: dat.main.temp,
-        wind: { speed: dat.wind.speed, dir: degToDirection(dat.wind.deg) },
-        pressure: dat.main.pressure,
-        humidity: dat.main.humidity,
-        main: dat.weather[0].main,
-        desc: dat.weather[0].description,
-        icon: `${iconBaseURL + dat.weather[0].icon}.png`
-      });
-    }
-  });
-}
-
-function fetchForecast(cityid, count, cb) {
-  const url = `http://api.openweathermap.org/data/2.5/forecast?units=metric&id=${cityid}&appid=${APPID}`;
-  _httpreq2.default.get(url, (err, res) => {
-    const raw = JSON.parse(res.body);
-    if (raw.list) {
-      const dat = raw.list.slice(0, count);
-      cb(dat.map(d => {
-        const date = new Date(d.dt * 1000);
-        return {
-          time: `${pad(date.getHours(), 2)}:${pad(date.getMinutes(), 2)}`,
-          temp: d.main.temp,
-          wind: { speed: d.wind.speed, dir: degToDirection(d.wind.deg) },
-          main: d.weather[0].main,
-          desc: d.weather[0].description,
-          icon: `${iconBaseURL + d.weather[0].icon}.png`
-        };
-      }));
-    }
-  });
-}
-
-function degToDirection(deg) {
-  let dir = 'N';
-  for (const i in directions) {
-    if (deg > directions[i]) {
-      dir = i;
-    }
-  }
-  return dir;
-}
-
-module.exports = function (io) {
-  const context = {};
-  let firstTime = true;
-  const update = function (firstUpdateCb) {
-    const then = function () {
-      if (context.current && context.forecast && firstTime) {
-        firstUpdateCb();
-        firstTime = false;
-      }
-    };
-    fetchCurrent(CITYID, current => {
-      context.current = current;
-      then();
-    });
-    fetchForecast(CITYID, 6, forecast => {
-      context.forecast = forecast;
-      then();
-    });
-  };
-  update(() => {
-    const pushToClients = function (sock) {
-      sock.emit('weather', _mustache2.default.render(TEMPLATE, context));
-    };
-    io.on('connect', pushToClients);
-    pushToClients(io);
-  });
-  setInterval(update, 10 * 60 * 1000);
-};
-//# sourceMappingURL=weather.js.map
\ No newline at end of file
diff --git a/modules/weather.js.map b/modules/weather.js.map
deleted file mode 100644
index 06e6cbeed1725067935cc8b7723218d6bec7d15c..0000000000000000000000000000000000000000
--- a/modules/weather.js.map
+++ /dev/null
@@ -1 +0,0 @@
-{"version":3,"sources":["../src/weather.js"],"names":["APPID","CITYID","directions","NNE","NE","ENE","E","ESE","SE","SSE","S","SSW","SW","WSW","W","WNW","NW","NNW","N","iconBaseURL","TEMPLATE","readFileSync","fetchCurrent","cityid","cb","url","get","err","res","dat","JSON","parse","body","cod","temp","main","wind","speed","dir","degToDirection","deg","pressure","humidity","weather","desc","description","icon","fetchForecast","count","raw","list","slice","map","d","date","Date","dt","time","pad","getHours","getMinutes","i","module","exports","io","context","firstTime","update","firstUpdateCb","then","current","forecast","pushToClients","sock","emit","render","on","setInterval"],"mappings":"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","file":"weather.js","sourcesContent":["import fs from 'fs';\nimport httpreq from 'httpreq';\nimport Mustache from 'mustache';\n\n///CONFIG\nconst APPID = 'fdc3690e6f9a7572128fe4012b4a2500';\nconst CITYID = '2945024';\n\n/// STATICS\nconst directions = { NNE: 11.25, NE: 33.75, ENE: 56.25, E: 78.75, ESE: 101.25, SE: 123.75, SSE: 146.25, S: 168.75, SSW: 191.25, SW: 213.75, WSW: 236.25, W: 258.75, WNW: 281.25, NW: 303.75, NNW: 326.25, N: 348.75 };\nconst iconBaseURL = 'http://openweathermap.org/img/w/';\nconst TEMPLATE = fs.readFileSync('modules/weather/template.mustache', 'utf-8');\n\nfunction fetchCurrent(cityid, cb) {\n  const url = `http://api.openweathermap.org/data/2.5/weather?units=metric&id=${cityid}&appid=${APPID}`;\n  httpreq.get(url, (err, res) => {\n    const dat = JSON.parse(res.body);\n    if (dat.cod) {\n      cb({\n        temp: dat.main.temp,\n        wind: { speed: dat.wind.speed, dir: degToDirection(dat.wind.deg) },\n        pressure: dat.main.pressure,\n        humidity: dat.main.humidity,\n        main: dat.weather[0].main,\n        desc: dat.weather[0].description,\n        icon: `${iconBaseURL + dat.weather[0].icon }.png`,\n      });\n    }\n  });\n}\n\nfunction fetchForecast(cityid, count, cb) {\n  const url = `http://api.openweathermap.org/data/2.5/forecast?units=metric&id=${cityid}&appid=${APPID}`;\n  httpreq.get(url, (err, res) => {\n    const raw = JSON.parse(res.body);\n    if (raw.list) {\n      const dat = raw.list.slice(0, count);\n      cb(dat.map((d) => {\n        const date = new Date(d.dt * 1000);\n        return {\n          time: `${pad(date.getHours(), 2)}:${pad(date.getMinutes(), 2)}`,\n          temp: d.main.temp,\n          wind: { speed: d.wind.speed, dir: degToDirection(d.wind.deg) },\n          main: d.weather[0].main,\n          desc: d.weather[0].description,\n          icon: `${iconBaseURL + d.weather[0].icon }.png`,\n        };\n      }));\n    }\n  });\n}\n\nfunction degToDirection(deg) {\n  let dir = 'N';\n  for (const i in directions) {\n    if (deg > directions[i]) {\n      dir = i;\n    }\n  }\n  return dir;\n}\n\nmodule.exports = function(io) {\n  const context = {};\n  let firstTime = true;\n  const update = function(firstUpdateCb) {\n    const then = function() {\n      if (context.current && context.forecast && firstTime) {\n        firstUpdateCb();\n        firstTime = false;\n      }\n    };\n    fetchCurrent(CITYID, (current) => {\n      context.current = current;\n      then();\n    });\n    fetchForecast(CITYID, 6, (forecast) => {\n      context.forecast = forecast;\n      then();\n    });\n  };\n  update(() => {\n    const pushToClients = function(sock) {\n      sock.emit('weather', Mustache.render(TEMPLATE, context));\n    };\n    io.on('connect', pushToClients);\n    pushToClients(io);\n  });\n  setInterval(update, 10 * 60 * 1000);\n};\n"]}
\ No newline at end of file
diff --git a/modules/weather/template.mustache b/modules/weather/template.mustache
deleted file mode 100644
index 1a58453004ff2482011bbb1a34d6c785aa8d5557..0000000000000000000000000000000000000000
--- a/modules/weather/template.mustache
+++ /dev/null
@@ -1,43 +0,0 @@
-<h3>Current Weather <img src="/modules/weather/wundergroundLogo_4c_rev_horz.png"></img></h3>
-<div style="width: 200px">
-    <img src="{{current.icon}}" align="left">
-    <b>{{current.main}}</b><br>{{current.desc}}
-</div>
-<div style="padding-right: 10px">
-{{current.temp}} °C<br>{{current.pressure}} hPa
-</div>
-<div>
-<img src="/modules/weather/wind.png"> {{current.wind.speed}} km/h {{current.wind.dir}}<br>
-{{current.humidity}}% rel.H.
-</div>
-<h3 style="clear: left">Forecast</h3>
-<table>
-    <colgroup>
-        <col width="60px">
-        <col width="220px">
-        <col width="120px">
-        <col width="60px">
-    </colgroup>
-    <tr>
-        <th>Time</th>
-        <th>Weather</th>
-        <th colspan="2">Conditions</th>
-    </tr>
-    {{#forecast}}
-        <tr>
-            <td>{{time}}</td>
-            <td>
-                <img src="{{icon}}" align="left">
-                <b>{{main}}</b><br>{{desc}}
-            </td>
-            <td>
-                {{temp}} °C<br>
-                <img src="/modules/weather/wind.png">
-                {{wind.speed}} km/h
-            </td>
-            <td>
-                <br>{{wind.dir}}
-            </td>
-        </tr>
-    {{/forecast}}
-</table>
diff --git a/package.json b/package.json
index 04803b78e3d4459e3bf47a7816c30c8026f3d327..1184242da91557251659da66ecf2093725ba9526 100644
--- a/package.json
+++ b/package.json
@@ -4,6 +4,7 @@
   "description": "",
   "main": "main.js",
   "dependencies": {
+    "babel-polyfill": "^6.23.0",
     "ee-first": "^1.1.1",
     "express": "^4.13.3",
     "httpreq": "^0.4.13",
@@ -18,6 +19,7 @@
   "devDependencies": {
     "babel": "^6.23.0",
     "babel-cli": "^6.23.0",
+    "babel-preset-es2015": "^6.22.0",
     "babel-preset-node6": "^11.0.0",
     "eslint": "^3.15.0",
     "eslint-config-marudor": "^4.1.2",
diff --git a/src/main.js b/src/main.js
new file mode 100644
index 0000000000000000000000000000000000000000..c8134dd161e2be284b5a2d97c09f0daf78977288
--- /dev/null
+++ b/src/main.js
@@ -0,0 +1,41 @@
+/* eslint no-console: 0 */
+require('babel-polyfill')
+const express = require('express');
+const app = express();
+const server = require('http').Server(app);
+const io = require('socket.io')(server);
+
+server.listen(8000);
+
+app.use(express.static(`${__dirname }/../public`));
+
+const instanceClients = [];
+io.on('connection', (socket) => {
+    socket.on('ident', (client) => {
+        if (instanceClients.indexOf(client) === -1) {
+            instanceClients.push(client);
+            socket.emit('meta', 'reload');
+        }
+    });
+});
+
+// for reasons
+global.DOW = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
+global.pad = function(n, width, z = '0') {
+    // eslint-disable-next-line
+    n = String(n);
+    return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n;
+};
+
+const normalizedPath = require('path').join(__dirname);
+require('fs').readdirSync(normalizedPath).forEach((file) => {
+    if (file.endsWith('.js') && !file.includes('main.js')) {
+        try {
+            require(`./${ file}`)(io);
+            console.log(`${file} loaded`);
+        } catch (e) {
+            console.log(`Error loading ${file}`);
+            console.log(e);
+        }
+    }
+});
diff --git a/yarn.lock b/yarn.lock
index a01f2e0e385b354b24015dc07187502cdcd1d2bc..74bb4ede5cb26d8f895e1ac4f275a53b58b443cc 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -225,6 +225,74 @@ babel-generator@^6.23.0:
     source-map "^0.5.0"
     trim-right "^1.0.1"
 
+babel-helper-call-delegate@^6.22.0:
+  version "6.22.0"
+  resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.22.0.tgz#119921b56120f17e9dae3f74b4f5cc7bcc1b37ef"
+  dependencies:
+    babel-helper-hoist-variables "^6.22.0"
+    babel-runtime "^6.22.0"
+    babel-traverse "^6.22.0"
+    babel-types "^6.22.0"
+
+babel-helper-define-map@^6.23.0:
+  version "6.23.0"
+  resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-6.23.0.tgz#1444f960c9691d69a2ced6a205315f8fd00804e7"
+  dependencies:
+    babel-helper-function-name "^6.23.0"
+    babel-runtime "^6.22.0"
+    babel-types "^6.23.0"
+    lodash "^4.2.0"
+
+babel-helper-function-name@^6.22.0, babel-helper-function-name@^6.23.0:
+  version "6.23.0"
+  resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.23.0.tgz#25742d67175c8903dbe4b6cb9d9e1fcb8dcf23a6"
+  dependencies:
+    babel-helper-get-function-arity "^6.22.0"
+    babel-runtime "^6.22.0"
+    babel-template "^6.23.0"
+    babel-traverse "^6.23.0"
+    babel-types "^6.23.0"
+
+babel-helper-get-function-arity@^6.22.0:
+  version "6.22.0"
+  resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.22.0.tgz#0beb464ad69dc7347410ac6ade9f03a50634f5ce"
+  dependencies:
+    babel-runtime "^6.22.0"
+    babel-types "^6.22.0"
+
+babel-helper-hoist-variables@^6.22.0:
+  version "6.22.0"
+  resolved "https://registry.yarnpkg.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.22.0.tgz#3eacbf731d80705845dd2e9718f600cfb9b4ba72"
+  dependencies:
+    babel-runtime "^6.22.0"
+    babel-types "^6.22.0"
+
+babel-helper-optimise-call-expression@^6.23.0:
+  version "6.23.0"
+  resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.23.0.tgz#f3ee7eed355b4282138b33d02b78369e470622f5"
+  dependencies:
+    babel-runtime "^6.22.0"
+    babel-types "^6.23.0"
+
+babel-helper-regex@^6.22.0:
+  version "6.22.0"
+  resolved "https://registry.yarnpkg.com/babel-helper-regex/-/babel-helper-regex-6.22.0.tgz#79f532be1647b1f0ee3474b5f5c3da58001d247d"
+  dependencies:
+    babel-runtime "^6.22.0"
+    babel-types "^6.22.0"
+    lodash "^4.2.0"
+
+babel-helper-replace-supers@^6.22.0, babel-helper-replace-supers@^6.23.0:
+  version "6.23.0"
+  resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.23.0.tgz#eeaf8ad9b58ec4337ca94223bacdca1f8d9b4bfd"
+  dependencies:
+    babel-helper-optimise-call-expression "^6.23.0"
+    babel-messages "^6.23.0"
+    babel-runtime "^6.22.0"
+    babel-template "^6.23.0"
+    babel-traverse "^6.23.0"
+    babel-types "^6.23.0"
+
 babel-helpers@^6.23.0:
   version "6.23.0"
   resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.23.0.tgz#4f8f2e092d0b6a8808a4bde79c27f1e2ecf0d992"
@@ -238,11 +306,101 @@ babel-messages@^6.23.0:
   dependencies:
     babel-runtime "^6.22.0"
 
+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-syntax-trailing-function-commas@^6.5.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-es2015-modules-commonjs@^6.7.4:
+babel-plugin-transform-es2015-arrow-functions@^6.22.0:
+  version "6.22.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221"
+  dependencies:
+    babel-runtime "^6.22.0"
+
+babel-plugin-transform-es2015-block-scoped-functions@^6.22.0:
+  version "6.22.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz#bbc51b49f964d70cb8d8e0b94e820246ce3a6141"
+  dependencies:
+    babel-runtime "^6.22.0"
+
+babel-plugin-transform-es2015-block-scoping@^6.22.0:
+  version "6.23.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.23.0.tgz#e48895cf0b375be148cd7c8879b422707a053b51"
+  dependencies:
+    babel-runtime "^6.22.0"
+    babel-template "^6.23.0"
+    babel-traverse "^6.23.0"
+    babel-types "^6.23.0"
+    lodash "^4.2.0"
+
+babel-plugin-transform-es2015-classes@^6.22.0:
+  version "6.23.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.23.0.tgz#49b53f326202a2fd1b3bbaa5e2edd8a4f78643c1"
+  dependencies:
+    babel-helper-define-map "^6.23.0"
+    babel-helper-function-name "^6.23.0"
+    babel-helper-optimise-call-expression "^6.23.0"
+    babel-helper-replace-supers "^6.23.0"
+    babel-messages "^6.23.0"
+    babel-runtime "^6.22.0"
+    babel-template "^6.23.0"
+    babel-traverse "^6.23.0"
+    babel-types "^6.23.0"
+
+babel-plugin-transform-es2015-computed-properties@^6.22.0:
+  version "6.22.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.22.0.tgz#7c383e9629bba4820c11b0425bdd6290f7f057e7"
+  dependencies:
+    babel-runtime "^6.22.0"
+    babel-template "^6.22.0"
+
+babel-plugin-transform-es2015-destructuring@^6.22.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.22.0:
+  version "6.22.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.22.0.tgz#672397031c21610d72dd2bbb0ba9fb6277e1c36b"
+  dependencies:
+    babel-runtime "^6.22.0"
+    babel-types "^6.22.0"
+
+babel-plugin-transform-es2015-for-of@^6.22.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.22.0:
+  version "6.22.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.22.0.tgz#f5fcc8b09093f9a23c76ac3d9e392c3ec4b77104"
+  dependencies:
+    babel-helper-function-name "^6.22.0"
+    babel-runtime "^6.22.0"
+    babel-types "^6.22.0"
+
+babel-plugin-transform-es2015-literals@^6.22.0:
+  version "6.22.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz#4f54a02d6cd66cf915280019a31d31925377ca2e"
+  dependencies:
+    babel-runtime "^6.22.0"
+
+babel-plugin-transform-es2015-modules-amd@^6.22.0:
+  version "6.22.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.22.0.tgz#bf69cd34889a41c33d90dfb740e0091ccff52f21"
+  dependencies:
+    babel-plugin-transform-es2015-modules-commonjs "^6.22.0"
+    babel-runtime "^6.22.0"
+    babel-template "^6.22.0"
+
+babel-plugin-transform-es2015-modules-commonjs@^6.22.0, babel-plugin-transform-es2015-modules-commonjs@^6.7.4:
   version "6.23.0"
   resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.23.0.tgz#cba7aa6379fb7ec99250e6d46de2973aaffa7b92"
   dependencies:
@@ -251,6 +409,87 @@ babel-plugin-transform-es2015-modules-commonjs@^6.7.4:
     babel-template "^6.23.0"
     babel-types "^6.23.0"
 
+babel-plugin-transform-es2015-modules-systemjs@^6.22.0:
+  version "6.23.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.23.0.tgz#ae3469227ffac39b0310d90fec73bfdc4f6317b0"
+  dependencies:
+    babel-helper-hoist-variables "^6.22.0"
+    babel-runtime "^6.22.0"
+    babel-template "^6.23.0"
+
+babel-plugin-transform-es2015-modules-umd@^6.22.0:
+  version "6.23.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.23.0.tgz#8d284ae2e19ed8fe21d2b1b26d6e7e0fcd94f0f1"
+  dependencies:
+    babel-plugin-transform-es2015-modules-amd "^6.22.0"
+    babel-runtime "^6.22.0"
+    babel-template "^6.23.0"
+
+babel-plugin-transform-es2015-object-super@^6.22.0:
+  version "6.22.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.22.0.tgz#daa60e114a042ea769dd53fe528fc82311eb98fc"
+  dependencies:
+    babel-helper-replace-supers "^6.22.0"
+    babel-runtime "^6.22.0"
+
+babel-plugin-transform-es2015-parameters@^6.22.0:
+  version "6.23.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.23.0.tgz#3a2aabb70c8af945d5ce386f1a4250625a83ae3b"
+  dependencies:
+    babel-helper-call-delegate "^6.22.0"
+    babel-helper-get-function-arity "^6.22.0"
+    babel-runtime "^6.22.0"
+    babel-template "^6.23.0"
+    babel-traverse "^6.23.0"
+    babel-types "^6.23.0"
+
+babel-plugin-transform-es2015-shorthand-properties@^6.22.0:
+  version "6.22.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.22.0.tgz#8ba776e0affaa60bff21e921403b8a652a2ff723"
+  dependencies:
+    babel-runtime "^6.22.0"
+    babel-types "^6.22.0"
+
+babel-plugin-transform-es2015-spread@^6.22.0:
+  version "6.22.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz#d6d68a99f89aedc4536c81a542e8dd9f1746f8d1"
+  dependencies:
+    babel-runtime "^6.22.0"
+
+babel-plugin-transform-es2015-sticky-regex@^6.22.0:
+  version "6.22.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.22.0.tgz#ab316829e866ee3f4b9eb96939757d19a5bc4593"
+  dependencies:
+    babel-helper-regex "^6.22.0"
+    babel-runtime "^6.22.0"
+    babel-types "^6.22.0"
+
+babel-plugin-transform-es2015-template-literals@^6.22.0:
+  version "6.22.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz#a84b3450f7e9f8f1f6839d6d687da84bb1236d8d"
+  dependencies:
+    babel-runtime "^6.22.0"
+
+babel-plugin-transform-es2015-typeof-symbol@^6.22.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.22.0:
+  version "6.22.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.22.0.tgz#8d9cc27e7ee1decfe65454fb986452a04a613d20"
+  dependencies:
+    babel-helper-regex "^6.22.0"
+    babel-runtime "^6.22.0"
+    regexpu-core "^2.0.0"
+
+babel-plugin-transform-regenerator@^6.22.0:
+  version "6.22.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.22.0.tgz#65740593a319c44522157538d690b84094617ea6"
+  dependencies:
+    regenerator-transform "0.9.8"
+
 babel-plugin-transform-strict-mode@^6.22.0:
   version "6.22.0"
   resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.22.0.tgz#e008df01340fdc87e959da65991b7e05970c8c7c"
@@ -266,6 +505,35 @@ babel-polyfill@^6.23.0:
     core-js "^2.4.0"
     regenerator-runtime "^0.10.0"
 
+babel-preset-es2015@^6.22.0:
+  version "6.22.0"
+  resolved "https://registry.yarnpkg.com/babel-preset-es2015/-/babel-preset-es2015-6.22.0.tgz#af5a98ecb35eb8af764ad8a5a05eb36dc4386835"
+  dependencies:
+    babel-plugin-check-es2015-constants "^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.22.0"
+    babel-plugin-transform-es2015-classes "^6.22.0"
+    babel-plugin-transform-es2015-computed-properties "^6.22.0"
+    babel-plugin-transform-es2015-destructuring "^6.22.0"
+    babel-plugin-transform-es2015-duplicate-keys "^6.22.0"
+    babel-plugin-transform-es2015-for-of "^6.22.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.22.0"
+    babel-plugin-transform-es2015-modules-systemjs "^6.22.0"
+    babel-plugin-transform-es2015-modules-umd "^6.22.0"
+    babel-plugin-transform-es2015-object-super "^6.22.0"
+    babel-plugin-transform-es2015-parameters "^6.22.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.22.0"
+    babel-plugin-transform-es2015-unicode-regex "^6.22.0"
+    babel-plugin-transform-regenerator "^6.22.0"
+
 babel-preset-node6@^11.0.0:
   version "11.0.0"
   resolved "https://registry.yarnpkg.com/babel-preset-node6/-/babel-preset-node6-11.0.0.tgz#0835994517248985a29d18f6d465dab16bb8a7d8"
@@ -285,14 +553,14 @@ babel-register@^6.23.0:
     mkdirp "^0.5.1"
     source-map-support "^0.4.2"
 
-babel-runtime@^6.22.0:
+babel-runtime@^6.18.0, babel-runtime@^6.22.0:
   version "6.23.0"
   resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.23.0.tgz#0a9489f144de70efb3ce4300accdb329e2fc543b"
   dependencies:
     core-js "^2.4.0"
     regenerator-runtime "^0.10.0"
 
-babel-template@^6.23.0:
+babel-template@^6.22.0, babel-template@^6.23.0:
   version "6.23.0"
   resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.23.0.tgz#04d4f270adbb3aa704a8143ae26faa529238e638"
   dependencies:
@@ -302,7 +570,7 @@ babel-template@^6.23.0:
     babylon "^6.11.0"
     lodash "^4.2.0"
 
-babel-traverse@^6.15.0, babel-traverse@^6.23.0, babel-traverse@^6.23.1:
+babel-traverse@^6.15.0, babel-traverse@^6.22.0, babel-traverse@^6.23.0, babel-traverse@^6.23.1:
   version "6.23.1"
   resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.23.1.tgz#d3cb59010ecd06a97d81310065f966b699e14f48"
   dependencies:
@@ -316,7 +584,7 @@ babel-traverse@^6.15.0, babel-traverse@^6.23.0, babel-traverse@^6.23.1:
     invariant "^2.2.0"
     lodash "^4.2.0"
 
-babel-types@^6.15.0, babel-types@^6.22.0, babel-types@^6.23.0:
+babel-types@^6.15.0, babel-types@^6.19.0, babel-types@^6.22.0, babel-types@^6.23.0:
   version "6.23.0"
   resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.23.0.tgz#bb17179d7538bad38cd0c9e115d340f77e7e9acf"
   dependencies:
@@ -1557,6 +1825,10 @@ jsesc@^1.3.0:
   version "1.3.0"
   resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b"
 
+jsesc@~0.5.0:
+  version "0.5.0"
+  resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d"
+
 json-schema@0.2.3:
   version "0.2.3"
   resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
@@ -2166,10 +2438,22 @@ rechoir@^0.6.2:
   dependencies:
     resolve "^1.1.6"
 
+regenerate@^1.2.1:
+  version "1.3.2"
+  resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.3.2.tgz#d1941c67bad437e1be76433add5b385f95b19260"
+
 regenerator-runtime@^0.10.0:
   version "0.10.3"
   resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz#8c4367a904b51ea62a908ac310bf99ff90a82a3e"
 
+regenerator-transform@0.9.8:
+  version "0.9.8"
+  resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.9.8.tgz#0f88bb2bc03932ddb7b6b7312e68078f01026d6c"
+  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"
@@ -2177,12 +2461,30 @@ regex-cache@^0.4.2:
     is-equal-shallow "^0.1.3"
     is-primitive "^2.0.0"
 
+regexpu-core@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240"
+  dependencies:
+    regenerate "^1.2.1"
+    regjsgen "^0.2.0"
+    regjsparser "^0.1.4"
+
 registry-url@^3.0.0:
   version "3.1.0"
   resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-3.1.0.tgz#3d4ef870f73dde1d77f0cf9a381432444e174942"
   dependencies:
     rc "^1.0.1"
 
+regjsgen@^0.2.0:
+  version "0.2.0"
+  resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7"
+
+regjsparser@^0.1.4:
+  version "0.1.5"
+  resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c"
+  dependencies:
+    jsesc "~0.5.0"
+
 repeat-element@^1.1.2:
   version "1.1.2"
   resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a"