diff --git a/.gitignore b/.gitignore
index 7404c57..03b8502 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,6 +4,7 @@
 atlassian-ide-plugin.xml
 node_modules/
 typings/
-app/**/*.js
-app/**/*.js.map
+src/**/*.js
+src/**/*.js.map
 npm-debug.log
+dist/
diff --git a/config/helpers.js b/config/helpers.js
new file mode 100644
index 0000000..adfb603
--- /dev/null
+++ b/config/helpers.js
@@ -0,0 +1,7 @@
+var path = require('path');
+var _root = path.resolve(__dirname, '..');
+function root(args) {
+    args = Array.prototype.slice.call(arguments, 0);
+    return path.join.apply(path, [_root].concat(args));
+}
+exports.root = root;
diff --git a/config/webpack.common.js b/config/webpack.common.js
new file mode 100644
index 0000000..37a66be
--- /dev/null
+++ b/config/webpack.common.js
@@ -0,0 +1,76 @@
+var webpack = require('webpack');
+var HtmlWebpackPlugin = require('html-webpack-plugin');
+var ExtractTextPlugin = require('extract-text-webpack-plugin');
+var helpers = require('./helpers');
+
+module.exports = {
+    entry: {
+        'polyfills': './src/polyfills.ts',
+        'vendor': './src/vendor.ts',
+        'app': './src/main.ts'
+    },
+
+    resolve: {
+        extensions: ['.ts', '.js']
+    },
+
+    module: {
+        rules: [
+            {
+                test: /\.ts$/,
+                loaders: [
+                    {
+                        loader: 'awesome-typescript-loader',
+                        options: {
+                            configFileName: helpers.root('src', 'tsconfig.json')
+                        }
+                    },
+                    'angular2-template-loader'
+                ]
+            },
+            {
+                test: /\.html$/,
+                use: 'html-loader'
+            },
+            {
+                test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/,
+                use: 'file-loader?name=assets/[name].[hash].[ext]'
+            },
+            // {
+            //     test: /\.css$/,
+            //     exclude: helpers.root('src', 'app'),
+            //     use: ExtractTextPlugin.extract({
+            //         fallback: 'style-loader',
+            //         use: 'css-loader?sourceMap'
+            //     })
+            // },
+            {
+                test: /\.css$/,
+                include: helpers.root('src', 'app'),
+                use: 'raw-loader'
+            }
+        ]
+    },
+
+    plugins: [
+        // Workaround for angular/angular#11580
+        new webpack.ContextReplacementPlugin(
+            // The (\\|\/) piece accounts for path separators in *nix and Windows
+            /angular(\\|\/)core(\\|\/)(esm(\\|\/)src|src)(\\|\/)linker/,
+            helpers.root('./src'), // location of your src
+            {} // a map of your routes
+        ),
+
+        new webpack.optimize.CommonsChunkPlugin({
+            name: ['app', 'vendor', 'polyfills']
+        }),
+
+        new HtmlWebpackPlugin({
+            template: 'src/index.html'
+        }),
+
+        new webpack.optimize.UglifyJsPlugin({
+            comments: false
+        })
+    ]
+};
diff --git a/config/webpack.dev.js b/config/webpack.dev.js
new file mode 100644
index 0000000..7f3c504
--- /dev/null
+++ b/config/webpack.dev.js
@@ -0,0 +1,24 @@
+var webpackMerge = require('webpack-merge');
+var ExtractTextPlugin = require('extract-text-webpack-plugin');
+var commonConfig = require('./webpack.common.js');
+var helpers = require('./helpers');
+
+module.exports = webpackMerge(commonConfig, {
+    devtool: 'cheap-module-eval-source-map',
+
+    output: {
+        path: helpers.root('dist'),
+        publicPath: 'http://localhost:8080/',
+        filename: '[name].js',
+        chunkFilename: '[id].chunk.js'
+    },
+
+    plugins: [
+        new ExtractTextPlugin('[name].css')
+    ],
+
+    devServer: {
+        historyApiFallback: true,
+        stats: 'minimal'
+    }
+});
diff --git a/karma.conf.js b/karma.conf.js
new file mode 100644
index 0000000..9649b15
--- /dev/null
+++ b/karma.conf.js
@@ -0,0 +1 @@
+module.exports = require('./config/karma.conf.js');
diff --git a/package.json b/package.json
index 39d3c79..ff786d3 100644
--- a/package.json
+++ b/package.json
@@ -3,7 +3,10 @@
   "version": "1.0.0-alpha.1",
   "description": "Convert to and fro!",
   "keywords": [
-    "dencode", "conversion", "converter", "convert"
+    "dencode",
+    "conversion",
+    "converter",
+    "convert"
   ],
   "author": {
     "name": "Manuel Friedli",
@@ -13,35 +16,48 @@
   "homepage": "https://test.friedli.info/~manuel/dencode",
   "repository": "https://gittr.ch/manuel/dencode.org.git",
   "dependencies": {
-    "@angular/common": "2.0.0",
-    "@angular/compiler": "2.0.0",
-    "@angular/core": "2.0.0",
-    "@angular/forms": "2.0.0",
-    "@angular/platform-browser": "2.0.0",
-    "@angular/platform-browser-dynamic": "2.0.0",
-    "@angular/upgrade": "2.0.0",
-    "bootstrap": "^3.3.6",
-    "core-js": "^2.4.0",
-    "reflect-metadata": "^0.1.3",
-    "rxjs": "5.0.0-beta.12",
-    "systemjs": "^0.19.27",
-    "zone.js": "^0.6.12",
+    "@angular/common": "~2.4.0",
+    "@angular/compiler": "~2.4.0",
+    "@angular/core": "~2.4.0",
+    "@angular/forms": "~2.4.0",
+    "@angular/platform-browser": "~2.4.0",
+    "@angular/platform-browser-dynamic": "~2.4.0",
+    "core-js": "^2.4.1",
+    "rxjs": "5.0.1",
+    "zone.js": "^0.7.4",
+    "bootstrap": "^3.3.0",
     "quoted-printable": "^1.0.0",
-    "utf8": "^2.1.1",
-    "punycode": "1.4.1"
+    "utf8": "^2.1.0",
+    "punycode": "^1.4.0"
   },
   "devDependencies": {
-    "concurrently": "^2.2.0",
-    "lite-server": "^2.2.0",
-    "typescript": "^2.0.2",
-    "typings": "^1.3.2"
+    "@types/node": "^6.0.45",
+    "@types/jasmine": "2.5.36",
+    "angular2-template-loader": "^0.6.0",
+    "awesome-typescript-loader": "^3.0.4",
+    "css-loader": "^0.26.1",
+    "extract-text-webpack-plugin": "2.0.0-beta.5",
+    "file-loader": "^0.9.0",
+    "html-loader": "^0.4.3",
+    "html-webpack-plugin": "^2.16.1",
+    "jasmine-core": "^2.4.1",
+    "karma": "^1.2.0",
+    "karma-chrome-launcher": "^2.0.0",
+    "karma-jasmine": "^1.0.2",
+    "karma-sourcemap-loader": "^0.3.7",
+    "karma-webpack": "^2.0.1",
+    "null-loader": "^0.1.1",
+    "raw-loader": "^0.5.1",
+    "rimraf": "^2.5.2",
+    "style-loader": "^0.13.1",
+    "typescript": "~2.0.10",
+    "webpack": "2.2.1",
+    "webpack-dev-server": "2.4.1",
+    "webpack-merge": "^3.0.0"
   },
   "scripts": {
-    "start": "tsc && concurrently \"npm run tsc:w\" \"npm run lite\"",
-    "lite": "lite-server",
-    "postinstall": "typings install",
-    "tsc": "tsc",
-    "tsc:w": "tsc -w",
-    "typings": "typings"
+    "start": "webpack-dev-server --inline --progress --port 8080",
+    "test": "karma start",
+    "build": "rimraf dist && webpack --config config/webpack.prod.js --progress --profile --bail"
   }
 }
diff --git a/abeezee-regular.woff b/src/abeezee-regular.woff
similarity index 100%
rename from abeezee-regular.woff
rename to src/abeezee-regular.woff
diff --git a/app/app.component.css b/src/app/app.component.css
similarity index 100%
rename from app/app.component.css
rename to src/app/app.component.css
diff --git a/app/app.component.html b/src/app/app.component.html
similarity index 100%
rename from app/app.component.html
rename to src/app/app.component.html
diff --git a/app/app.component.ts b/src/app/app.component.ts
similarity index 100%
rename from app/app.component.ts
rename to src/app/app.component.ts
diff --git a/app/app.module.ts b/src/app/app.module.ts
similarity index 100%
rename from app/app.module.ts
rename to src/app/app.module.ts
diff --git a/app/converter/base64decoder.ts b/src/app/converter/base64decoder.ts
similarity index 100%
rename from app/converter/base64decoder.ts
rename to src/app/converter/base64decoder.ts
diff --git a/app/converter/base64encoder.ts b/src/app/converter/base64encoder.ts
similarity index 100%
rename from app/converter/base64encoder.ts
rename to src/app/converter/base64encoder.ts
diff --git a/app/converter/bintodecconverter.ts b/src/app/converter/bintodecconverter.ts
similarity index 99%
rename from app/converter/bintodecconverter.ts
rename to src/app/converter/bintodecconverter.ts
index 0b4cbd7..33d73ba 100644
--- a/app/converter/bintodecconverter.ts
+++ b/src/app/converter/bintodecconverter.ts
@@ -1,4 +1,5 @@
 import {Converter} from "./converter";
+
 export class BinToDecConverter implements Converter {
     getDisplayname():string {
         return "Convert binary to decimal";
diff --git a/app/converter/converter.ts b/src/app/converter/converter.ts
similarity index 100%
rename from app/converter/converter.ts
rename to src/app/converter/converter.ts
diff --git a/app/converter/dectobinconverter.ts b/src/app/converter/dectobinconverter.ts
similarity index 99%
rename from app/converter/dectobinconverter.ts
rename to src/app/converter/dectobinconverter.ts
index b64a310..c457d4c 100644
--- a/app/converter/dectobinconverter.ts
+++ b/src/app/converter/dectobinconverter.ts
@@ -1,4 +1,5 @@
 import {Converter} from "./converter";
+
 export class DecToBinConverter implements Converter {
     getDisplayname():string {
         return "Convert decimal to binary";
diff --git a/app/converter/dectohexconverter.ts b/src/app/converter/dectohexconverter.ts
similarity index 99%
rename from app/converter/dectohexconverter.ts
rename to src/app/converter/dectohexconverter.ts
index b033792..4050643 100644
--- a/app/converter/dectohexconverter.ts
+++ b/src/app/converter/dectohexconverter.ts
@@ -1,4 +1,5 @@
 import {Converter} from "./converter";
+
 export class DecToHexConverter implements Converter {
     getDisplayname():string {
         return "Convert decimal to hexadecimal";
diff --git a/app/converter/hextodecconverter.ts b/src/app/converter/hextodecconverter.ts
similarity index 99%
rename from app/converter/hextodecconverter.ts
rename to src/app/converter/hextodecconverter.ts
index 2dcdad2..68b8c27 100644
--- a/app/converter/hextodecconverter.ts
+++ b/src/app/converter/hextodecconverter.ts
@@ -1,4 +1,5 @@
 import {Converter} from "./converter";
+
 export class HexToDecConverter implements Converter {
     getDisplayname():string {
         return "Convert hexadecimal to decimal";
diff --git a/app/converter/htmlentitiesdecoder.ts b/src/app/converter/htmlentitiesdecoder.ts
similarity index 100%
rename from app/converter/htmlentitiesdecoder.ts
rename to src/app/converter/htmlentitiesdecoder.ts
diff --git a/app/converter/htmlentitiesencoder.ts b/src/app/converter/htmlentitiesencoder.ts
similarity index 100%
rename from app/converter/htmlentitiesencoder.ts
rename to src/app/converter/htmlentitiesencoder.ts
diff --git a/app/converter/punycodedecoder.ts b/src/app/converter/punycodedecoder.ts
similarity index 100%
rename from app/converter/punycodedecoder.ts
rename to src/app/converter/punycodedecoder.ts
diff --git a/app/converter/punycodeencoder.ts b/src/app/converter/punycodeencoder.ts
similarity index 100%
rename from app/converter/punycodeencoder.ts
rename to src/app/converter/punycodeencoder.ts
diff --git a/app/converter/quotedprintabledecoder.ts b/src/app/converter/quotedprintabledecoder.ts
similarity index 100%
rename from app/converter/quotedprintabledecoder.ts
rename to src/app/converter/quotedprintabledecoder.ts
diff --git a/app/converter/quotedprintableencoder.ts b/src/app/converter/quotedprintableencoder.ts
similarity index 100%
rename from app/converter/quotedprintableencoder.ts
rename to src/app/converter/quotedprintableencoder.ts
diff --git a/app/converter/uricomponentdecoder.ts b/src/app/converter/uricomponentdecoder.ts
similarity index 100%
rename from app/converter/uricomponentdecoder.ts
rename to src/app/converter/uricomponentdecoder.ts
diff --git a/app/converter/uricomponentencoder.ts b/src/app/converter/uricomponentencoder.ts
similarity index 100%
rename from app/converter/uricomponentencoder.ts
rename to src/app/converter/uricomponentencoder.ts
diff --git a/app/converter/uridecoder.ts b/src/app/converter/uridecoder.ts
similarity index 100%
rename from app/converter/uridecoder.ts
rename to src/app/converter/uridecoder.ts
diff --git a/app/converter/uriencoder.ts b/src/app/converter/uriencoder.ts
similarity index 100%
rename from app/converter/uriencoder.ts
rename to src/app/converter/uriencoder.ts
diff --git a/app/converterregistry.service.ts b/src/app/converterregistry.service.ts
similarity index 100%
rename from app/converterregistry.service.ts
rename to src/app/converterregistry.service.ts
diff --git a/app/inputcomponentmanager.service.ts b/src/app/inputcomponentmanager.service.ts
similarity index 100%
rename from app/inputcomponentmanager.service.ts
rename to src/app/inputcomponentmanager.service.ts
diff --git a/app/nativelibrarywrapper.service.ts b/src/app/nativelibrarywrapper.service.ts
similarity index 100%
rename from app/nativelibrarywrapper.service.ts
rename to src/app/nativelibrarywrapper.service.ts
diff --git a/app/step.ts b/src/app/step.ts
similarity index 99%
rename from app/step.ts
rename to src/app/step.ts
index fb4d584..d86c68f 100644
--- a/app/step.ts
+++ b/src/app/step.ts
@@ -1,4 +1,5 @@
 import {Converter} from "./converter/converter";
+
 export class Step {
     public content:string = "";
     public selectedConverter:Converter = undefined;
diff --git a/freemono.eot b/src/freemono.eot
similarity index 100%
rename from freemono.eot
rename to src/freemono.eot
diff --git a/freemono.svg b/src/freemono.svg
similarity index 100%
rename from freemono.svg
rename to src/freemono.svg
diff --git a/freemono.ttf b/src/freemono.ttf
similarity index 100%
rename from freemono.ttf
rename to src/freemono.ttf
diff --git a/freemono.woff b/src/freemono.woff
similarity index 100%
rename from freemono.woff
rename to src/freemono.woff
diff --git a/index.html b/src/index.html
similarity index 54%
rename from index.html
rename to src/index.html
index f12af09..5473fad 100644
--- a/index.html
+++ b/src/index.html
@@ -1,23 +1,27 @@
 <!DOCTYPE html>
+<!--
+  ~ Copyright (C) Schweizerische Bundesbahnen SBB, 2017.
+  -->
+
 <html>
 <head>
     <meta charset="UTF-8"/>
     <meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no"/>
     <title>Decode? Encode? DENcode!</title>
-    <script type="text/javascript" src="node_modules/core-js/client/shim.js"></script>
-    <script type="text/javascript" src="node_modules/zone.js/dist/zone.js"></script>
-    <script type="text/javascript" src="node_modules/reflect-metadata/Reflect.js"></script>
-    <script type="text/javascript" src="node_modules/systemjs/dist/system.src.js"></script>
-    <script type="text/javascript" src="node_modules/utf8/utf8.js"></script>
-    <script type="text/javascript" src="node_modules/quoted-printable/quoted-printable.js"></script>
-    <script type="text/javascript" src="node_modules/punycode/punycode.js"></script>
+    <!--<script type="text/javascript" src="node_modules/core-js/client/shim.js"></script>-->
+    <!--<script type="text/javascript" src="node_modules/zone.js/dist/zone.js"></script>-->
+    <!--<script type="text/javascript" src="node_modules/reflect-metadata/Reflect.js"></script>-->
+    <!--<script type="text/javascript" src="node_modules/systemjs/dist/system.src.js"></script>-->
+    <!--<script type="text/javascript" src="node_modules/utf8/utf8.js"></script>-->
+    <!--<script type="text/javascript" src="node_modules/quoted-printable/quoted-printable.js"></script>-->
+    <!--<script type="text/javascript" src="node_modules/punycode/punycode.js"></script>-->
 
-    <script type="text/javascript" src="systemjs.config.js"></script>
-    <script type="text/javascript">
-        System.import("app").catch(function (err) {
-            console.log(err);
-        });
-    </script>
+    <!--<script type="text/javascript" src="systemjs.config.js"></script>-->
+    <!--<script type="text/javascript">-->
+        <!--System.import("app").catch(function (err) {-->
+            <!--console.log(err);-->
+        <!--});-->
+    <!--</script>-->
     <style>
         @font-face {
             font-family: "ABeeZee";
diff --git a/app/main.ts b/src/main.ts
similarity index 74%
rename from app/main.ts
rename to src/main.ts
index c31c26f..1a7052b 100644
--- a/app/main.ts
+++ b/src/main.ts
@@ -1,4 +1,4 @@
 import {platformBrowserDynamic} from "@angular/platform-browser-dynamic";
-import {AppModule} from "./app.module";
+import {AppModule} from "./app/app.module";
 
 platformBrowserDynamic().bootstrapModule(AppModule);
diff --git a/src/polyfills.ts b/src/polyfills.ts
new file mode 100644
index 0000000..24bba2f
--- /dev/null
+++ b/src/polyfills.ts
@@ -0,0 +1,12 @@
+import "core-js/es6";
+import "core-js/es7/reflect";
+import "zone.js/dist/zone";
+require('zone.js/dist/zone');
+
+if (process.env.ENV === 'production') {
+    // Production
+} else {
+    // Development and test
+    Error['stackTraceLimit'] = Infinity;
+    require('zone.js/dist/long-stack-trace-zone');
+}
diff --git a/tsconfig.json b/src/tsconfig.json
similarity index 58%
rename from tsconfig.json
rename to src/tsconfig.json
index e6a6eac..d23f0db 100644
--- a/tsconfig.json
+++ b/src/tsconfig.json
@@ -1,12 +1,17 @@
 {
   "compilerOptions": {
+    "alwaysStrict": true,
     "target": "es5",
     "module": "commonjs",
     "moduleResolution": "node",
     "sourceMap": true,
     "emitDecoratorMetadata": true,
     "experimentalDecorators": true,
-    "removeComments": false,
-    "noImplicitAny": false
+    "lib": [
+      "es2015",
+      "dom"
+    ],
+    "noImplicitAny": true,
+    "suppressImplicitAnyIndexErrors": true
   }
 }
diff --git a/src/vendor.ts b/src/vendor.ts
new file mode 100644
index 0000000..0ea4119
--- /dev/null
+++ b/src/vendor.ts
@@ -0,0 +1,17 @@
+import "@angular/core";
+import "@angular/platform-browser";
+import "@angular/platform-browser-dynamic";
+import "@angular/forms";
+// import {Component, Injectable, NgModule, OnInit} from "@angular/core";
+// import {BrowserModule} from "@angular/platform-browser";
+// import {platformBrowserDynamic} from "@angular/platform-browser-dynamic";
+// import {FormsModule} from "@angular/forms";
+
+// // Angular
+// import '@angular/platform-browser-dynamic';
+// import '@angular/common';
+// import '@angular/http';
+// import '@angular/router';
+//
+// // RxJS
+// import 'rxjs';
diff --git a/typings.json b/typings.json
deleted file mode 100644
index c43d8b7..0000000
--- a/typings.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-  "name": "dencode.org",
-  "dependencies": {},
-  "globalDependencies": {
-    "core-js": "registry:dt/core-js#0.0.0+20160914114559",
-    "jasmine": "registry:dt/jasmine#2.2.0+20160621224255",
-    "node": "registry:dt/node#6.0.0+20160915134512"
-  }
-}
diff --git a/webpack.config.js b/webpack.config.js
new file mode 100644
index 0000000..26df33c
--- /dev/null
+++ b/webpack.config.js
@@ -0,0 +1 @@
+module.exports = require('./config/webpack.dev.js');