diff --git a/.babelrc b/.babelrc
new file mode 100644
index 0000000000000000000000000000000000000000..86ef2108793d6ca6d2358d3797446784a2a1e485
--- /dev/null
+++ b/.babelrc
@@ -0,0 +1,3 @@
+{
+    "presets": ["@babel/preset-env", "@babel/preset-react"]
+}
diff --git a/Makefile b/Makefile
index 6fd5535d7fe104a82cd50107fcc28ee20e7e7141..36d8a2e352252ca0657042cf6df29da6ea9d9f33 100644
--- a/Makefile
+++ b/Makefile
@@ -21,7 +21,8 @@ sass-watcher:
 
 .PHONY: js-watcher
 js-watcher:
-	$(YARN) run budo src/index.js:bundle.js --dir public --port $(PORT) --live -t babelify
+	# TODO: yarn run doesn't work..
+	./node_modules/.bin/budo src/index.js:bundle.js --dir public --port $(PORT) --live -- -t babelify
 
 
 # Dist
@@ -30,8 +31,10 @@ js-watcher:
 dist:
 	@mkdir -p "dist/${PACKAGE_NAME}-${VERSION}"
 	cp -avf public/index.html "dist/${PACKAGE_NAME}-${VERSION}/index.html"
+	# TODO: cache-invalidation with version string replaced in html file
+	cp -avf public/favicon.ico "dist/${PACKAGE_NAME}-${VERSION}/favicon.ico"
 	$(SASS) -t compressed src/style.scss "dist/${PACKAGE_NAME}-${VERSION}/bundle.css"
-	$(YARN) run browserify src/index.js -o "dist/${PACKAGE_NAME}-${VERSION}/bundle.js"
+	$(YARN) run -s browserify -t babelify src/index.js | $(YARN) run -s uglifyjs > "dist/${PACKAGE_NAME}-${VERSION}/bundle.js"
 	cd dist && tar --owner=0 --group=0 -czvf ${PACKAGE_NAME}-${VERSION}.tar.gz "${PACKAGE_NAME}-${VERSION}"
 
 
diff --git a/package.json b/package.json
index fe9f9c4e0949ff295c766d462d173f93b7438fe2..d4a08f5e7beddc381f3cbe2d370ae4350d5ef2d5 100644
--- a/package.json
+++ b/package.json
@@ -5,13 +5,19 @@
   "author": "Jelle van der Waa",
   "license": "MIT",
   "private": true,
-  "dependencies": {
-  },
+  "dependencies": {},
   "devDependencies": {
     "@babel/core": "^7.9.6",
+    "@babel/plugin-proposal-object-rest-spread": "^7.9.6",
+    "@babel/plugin-transform-react-jsx": "^7.9.4",
     "@babel/preset-env": "^7.9.6",
+    "@babel/preset-react": "^7.9.4",
     "babelify": "^10.0.0",
     "budo": "^11.6.3",
-    "bulma": "^0.8.2"
-  }
+    "bulma": "^0.8.2",
+    "react": "^16.13.1",
+    "react-dom": "^16.13.1",
+    "uglify-js": "^3.9.3"
+  },
+  "browserslist": "> 0.25%, not dead"
 }
diff --git a/public/index.html b/public/index.html
index f59bdba1d78037a91cab336db0dd8316cf230109..b0b86b9682baee4e5813e9523aa134b91f2c6c34 100644
--- a/public/index.html
+++ b/public/index.html
@@ -9,24 +9,7 @@
 		<link rel="shortcut icon" href="favicon.ico"/>
 	</head>
 	<body>
-		<section class="hero is-primary">
-			<div class="hero-body">
-				<div id="status" class="container">
-					<h1 class="title">Arch Linux Reproducible repository status</h1>
-					<p>Welcome to the official experimental Arch Linux <a href="https://github.com/kpcyrd/rebuilderd">rebuilderd</a> instance, this page shows the results of verification builds of official Arch Linux packages in the repositories in an effort to be fully reproducible. For more information read the <a href="https://reproducible-builds.org/">Reproducible Builds website</a> or join the <a href="ircs://chat.freenode.net/archlinux-reproducible">#archlinux-reproducible</a> IRC channel on <a href="https://freenode.net/">Freenode</a>.</p>
-					<br>
-				</div>
-			</div>
-		</section>
-		<section id="bad" class="section">
-			<div class="tile box has-background-danger">
-				<div class="content">
-					<p class='title is-5 has-text-white'>Unreproducible packages</p>
-					<ul id="packagesul">
-					</ul>
-				</div>
-			</div>
-		</section>
+		<div id="root"></div>
 		<footer class="footer">
 		<div class="content has-text-centered">
 			<p>
diff --git a/src/App.js b/src/App.js
new file mode 100644
index 0000000000000000000000000000000000000000..653afff216df07fbfafe9a654c588ac23d52547d
--- /dev/null
+++ b/src/App.js
@@ -0,0 +1,62 @@
+'use strict';
+
+const React = require('react');
+
+const {Header} = require('./Header');
+const {Body} = require('./Body');
+
+
+class App extends React.Component {
+  constructor(props) {
+    super(props);
+    this.state = {
+      fetchFailed: false,
+      suites: []
+    };
+  }
+
+  render() {
+    const { fetchFailed, suites } = this.state;
+    return (
+      <React.Fragment>
+        <Header fetchFailed={fetchFailed} suites={suites}/>
+        <Body fetchFailed={fetchFailed} suites={suites}/>
+      </React.Fragment>
+    );
+  }
+
+  componentDidMount() {
+    const url = '/api/v0/pkgs/list';
+
+    fetch(url).then((response) => {
+      if (!response.ok) {
+        this.setState({fetchFailed: true});
+        throw new Error(response.statusText);
+      }
+      return response.json();
+    }).then((data) => {
+      const suites = {};
+
+      for (let pkg of data) {
+        if (pkg.suite in suites) {
+          suites[pkg.suite].push(pkg);
+        } else {
+          suites[pkg.suite] = [pkg];
+        }
+      }
+
+      const suiteList = [];
+
+      for (let repo of Object.keys(suites).sort()) {
+        suiteList.push({name: repo, pkgs: suites[repo]});
+      }
+
+      this.setState({suites: suiteList});
+    }).catch((error) => {
+      console.log(error);
+      this.setState({fetchFailed: true});
+    });
+  }
+}
+
+module.exports = {App};
diff --git a/src/Body.js b/src/Body.js
new file mode 100644
index 0000000000000000000000000000000000000000..9ff0add1c27e42cd9641183bbf8c738403718c30
--- /dev/null
+++ b/src/Body.js
@@ -0,0 +1,31 @@
+'use strict';
+
+const React = require('react');
+
+const { Section } = require('./Section');
+
+
+class Body extends React.Component {
+  render() {
+    const { fetchFailed, suites } = this.props;
+
+    return (
+      <React.Fragment>
+      { fetchFailed &&
+      <section className="section">
+        <div className="tile box has-background-danger">
+          <div className="content has-text-centered">
+            <p className='title is-5 has-text-white'>An unexpected error occurred fetching the rebuild status</p>
+          </div>
+        </div>
+      </section>
+      }
+      {suites.map(suite =>
+        <Section key={suite.name} suite={suite}/>
+      )}
+      </React.Fragment>
+    )
+  }
+}
+
+module.exports = {Body};
diff --git a/src/Header.js b/src/Header.js
new file mode 100644
index 0000000000000000000000000000000000000000..148afc8f08a82f3bc26d4ccee62832d83fcb9ca0
--- /dev/null
+++ b/src/Header.js
@@ -0,0 +1,56 @@
+'use strict';
+
+const React = require('react');
+
+
+class Header extends React.Component {
+  calculateSuiteStats(data) {
+    let good = 0;
+    let bad = 0;
+    let unknown = 0;
+
+    for (let pkg of data) {
+      switch (pkg.status) {
+        case 'GOOD':
+          good++;
+          break
+        case 'BAD':
+          bad++;
+          break
+        case 'UNKWN':
+          unknown++;
+          break
+      }
+    }
+
+    const percentage = (good / data.length * 100).toFixed(1);
+    return {good, bad, unknown, percentage};
+  }
+
+  render() {
+    const {fetchFailed, suites } = this.props;
+    const suitesStats = [];
+
+    for (let suite of suites) {
+      const {good, bad, unknown, percentage} = this.calculateSuiteStats(suite.pkgs);
+      suitesStats.push({name: suite.name, good, bad, unknown, percentage});
+    }
+
+    return (
+      <section className="hero is-primary">
+        <div className="hero-body">
+          <div id="status" className="container">
+            <h1 className="title">Arch Linux Reproducible status</h1>
+  					<p>Welcome to the official experimental Arch Linux <a href="https://github.com/kpcyrd/rebuilderd">rebuilderd</a> instance, this page shows the results of verification builds of official Arch Linux packages in the repositories in an effort to be fully reproducible. For more information read the <a href="https://reproducible-builds.org/">Reproducible Builds website</a> or join the <a href="ircs://chat.freenode.net/archlinux-reproducible">#archlinux-reproducible</a> IRC channel on <a href="https://freenode.net/">Freenode</a>.</p>
+          <br/>
+          {!fetchFailed && suitesStats.map(function(repo, index) {
+            return <p key={ index }><a href={"#" + repo.name }>[{ repo.name }]</a> repository is { repo.percentage }% reproducible with { repo.bad } bad and { repo.unknown } unknown packages.</p>;
+          })}
+          </div>
+        </div>
+      </section>
+    );
+  }
+}
+
+module.exports = {Header};
diff --git a/src/Section.js b/src/Section.js
new file mode 100644
index 0000000000000000000000000000000000000000..8421fbd54c57c03e758ceacef7c708485450c9f4
--- /dev/null
+++ b/src/Section.js
@@ -0,0 +1,28 @@
+'use strict';
+
+const React = require('react');
+
+
+class Section extends React.Component {
+  render() {
+    const { suite } = this.props;
+    return (
+      <section key={suite.name} id={suite.name} className="section">
+        <div className="tile box has-background-danger">
+          <div className="content">
+            <p className='title is-5 has-text-white'>{ suite.name }</p>
+              <ul>
+              {suite.pkgs.map(function(pkg) { 
+                if (pkg.status == 'BAD') {
+                  return <li key={pkg.name}><p className="subtitle is-6 has-text-white">{pkg.name}-{pkg.version}</p></li>
+                }
+              })}
+              </ul>
+          </div>
+        </div>
+      </section>
+    )
+  }
+}
+
+module.exports = {Section};
diff --git a/src/index.js b/src/index.js
index db28e6a0cd7b01b54726497641752d0071ddf921..7ac45a74a460fa9fdb3aefb3fed6847fd135a72d 100644
--- a/src/index.js
+++ b/src/index.js
@@ -1,87 +1,8 @@
-function displayBadPackages(suites) {
-  const packagesList = document.getElementById("packagesul");
-  const fragment = document.createDocumentFragment();
+'use strict';
 
-  for (let suite of Object.values(suites).sort()) {
-    for (let pkg of suite) {
-      if (pkg.status == 'GOOD') {
-        continue
-      }
+const React = require('react');
+const ReactDOM = require('react-dom');
 
-      const li = document.createElement('li');
-      const p = document.createElement('p');
-      p.className = 'subtitle is-6 has-text-white';
-      p.textContent = `${pkg.suite} - ${pkg.name}-${pkg.version}`;
+const { App } = require('./App');
 
-      li.appendChild(p);
-      fragment.appendChild(li);
-    }
-  }
-
-  packagesList.appendChild(fragment);
-}
-
-function calculateSuiteStats(data) {
-  let good = 0;
-  let bad = 0;
-  let unknown = 0;
-
-  for (pkg of data) {
-    switch (pkg.status) {
-      case 'GOOD':
-        good++;
-        break
-      case 'BAD':
-        bad++;
-        break
-      case 'UNKWN':
-        unknown++;
-        break
-    }
-  }
-
-  reproPercentage = (good / data.length * 100).toFixed(1);
-  return {good, bad, unknown, reproPercentage};
-}
-
-function displayStats(suites) {
-  const elem = document.getElementById("status");
-  const fragment = document.createDocumentFragment();
-  for (let suite of Object.values(suites).sort()) {
-    const {good, bad, unknown, reproPercentage} = calculateSuiteStats(suite);
-
-    const h2 = document.createElement('h2');
-    const suiteName = suite[0].suite; 
-    h2.textContent = `[${suiteName}] repository is ${reproPercentage}% reproducible with ${bad} bad and ${unknown} unknown packages.`;
-
-    fragment.appendChild(h2);
-  }
-
-  elem.appendChild(fragment);
-}
-
-fetch(`/api/v0/pkgs/list`).then((response) => {
-  return response.json();
-}).then((data) => {
-  const suites = {};
-
-  for (pkg of data) {
-    if (pkg.suite in suites) {
-      suites[pkg.suite].push(pkg);
-    } else {
-      suites[pkg.suite] = [pkg];
-    }
-  }
-
-  displayStats(suites);
-  displayBadPackages(suites);
-}).catch(() => {
-  const elem = document.getElementById('status');
-  const div = document.createElement('div');
-  div.textContent = 'An unexpected erorr occurred fetching the rebuild status';
-  div.className = 'notification is-danger';
-
-  elem.appendChild(div);
-  const bad = document.getElementById('bad');
-  bad.innerHTML = '';
-});
+ReactDOM.render(<App />, document.getElementById('root'));
diff --git a/src/style.scss b/src/style.scss
index 6ea330223c2abc507a308171228185aabf889f8e..15612cba89f93956838a62320b8fc56f0d427a94 100644
--- a/src/style.scss
+++ b/src/style.scss
@@ -8,8 +8,25 @@ $link: #212952;
 @import "../node_modules/bulma/sass/elements/container.sass";
 @import "../node_modules/bulma/sass/elements/box.sass";
 @import "../node_modules/bulma/sass/elements/title.sass";
-@import "../node_modules/bulma/sass/elements/notification.sass";
 @import "../node_modules/bulma/sass/layout/footer.sass";
 @import "../node_modules/bulma/sass/layout/hero.sass";
 @import "../node_modules/bulma/sass/layout/section.sass";
 @import "../node_modules/bulma/sass/grid/tiles.sass";
+
+@media (min-width: 500px) {
+	ul {
+		columns: 2;
+	}
+}
+
+@media (min-width: 1024px) {
+	ul {
+		columns: 4;
+	}
+}
+
+@media (min-width: 2000px) {
+	ul {
+		columns: 8;
+	}
+}
diff --git a/webpack.config.js b/webpack.config.js
deleted file mode 100644
index 9d48bd63500f1dd910c0ba109d9a98c01da14495..0000000000000000000000000000000000000000
--- a/webpack.config.js
+++ /dev/null
@@ -1,56 +0,0 @@
-"use strict"
-
-const path = require('path');
-const TerserJSPlugin = require('terser-webpack-plugin');
-const MiniCssExtractPlugin = require('mini-css-extract-plugin')
-const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
-
-module.exports = {
-  mode: 'development',
-  entry: './src/index.js',
-  output: {
-    filename: 'main.js',
-    path: path.resolve(__dirname, 'dist'),
-  },
-  module: {
-    rules: [{
-      test: /\.scss$/,
-      use: [
-          MiniCssExtractPlugin.loader,
-          {
-            loader: 'css-loader'
-          },
-          {
-            loader: 'sass-loader',
-            options: {
-              sourceMap: true,
-              // options...
-            }
-          }
-        ]
-    },
-    {
-      test: /\.js$/,
-      exclude: /node_modules/,
-      loader: 'eslint-loader',
-      options: {
-        // eslint options (if necessary)
-      },
-   }],
-  },
-  externals: {
-    'Config': JSON.stringify(process.env.NODE_ENV === 'production' ? { 
-      apiPrefix: ''
-    } : {
-      apiPrefix: '/repro'
-    }),
-  },
-  optimization: {
-    minimizer: [new TerserJSPlugin({}), new OptimizeCSSAssetsPlugin({})],
-  },
-  plugins: [
-    new MiniCssExtractPlugin({
-      filename: 'css/style.css'
-    }),
-  ]
-};
diff --git a/yarn.lock b/yarn.lock
index 66357c329f068de64bf137ecb9ff77e334d82725..0afbb1794ee8ec2a5722a0517d5a961232e2fae6 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -50,6 +50,13 @@
     lodash "^4.17.13"
     source-map "^0.5.0"
 
+"@babel/helper-annotate-as-pure@^7.10.1":
+  version "7.10.1"
+  resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.1.tgz#f6d08acc6f70bbd59b436262553fb2e259a1a268"
+  integrity sha512-ewp3rvJEwLaHgyWGe4wQssC2vjks3E80WiUe2BpMb0KhreTjMROCbxXcEovTrbeGVdQct5VjQfrv9EgC+xMzCw==
+  dependencies:
+    "@babel/types" "^7.10.1"
+
 "@babel/helper-annotate-as-pure@^7.8.3":
   version "7.8.3"
   resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.8.3.tgz#60bc0bc657f63a0924ff9a4b4a0b24a13cf4deee"
@@ -65,6 +72,23 @@
     "@babel/helper-explode-assignable-expression" "^7.8.3"
     "@babel/types" "^7.8.3"
 
+"@babel/helper-builder-react-jsx-experimental@^7.10.1":
+  version "7.10.1"
+  resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx-experimental/-/helper-builder-react-jsx-experimental-7.10.1.tgz#9a7d58ad184d3ac3bafb1a452cec2bad7e4a0bc8"
+  integrity sha512-irQJ8kpQUV3JasXPSFQ+LCCtJSc5ceZrPFVj6TElR6XCHssi3jV8ch3odIrNtjJFRZZVbrOEfJMI79TPU/h1pQ==
+  dependencies:
+    "@babel/helper-annotate-as-pure" "^7.10.1"
+    "@babel/helper-module-imports" "^7.10.1"
+    "@babel/types" "^7.10.1"
+
+"@babel/helper-builder-react-jsx@^7.10.1":
+  version "7.10.1"
+  resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.10.1.tgz#a327f0cf983af5554701b1215de54a019f09b532"
+  integrity sha512-KXzzpyWhXgzjXIlJU1ZjIXzUPdej1suE6vzqgImZ/cpAsR/CC8gUcX4EWRmDfWz/cs6HOCPMBIJ3nKoXt3BFuw==
+  dependencies:
+    "@babel/helper-annotate-as-pure" "^7.10.1"
+    "@babel/types" "^7.10.1"
+
 "@babel/helper-compilation-targets@^7.9.6":
   version "7.9.6"
   resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.9.6.tgz#1e05b7ccc9d38d2f8b40b458b380a04dcfadd38a"
@@ -132,6 +156,13 @@
   dependencies:
     "@babel/types" "^7.8.3"
 
+"@babel/helper-module-imports@^7.10.1":
+  version "7.10.1"
+  resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.10.1.tgz#dd331bd45bccc566ce77004e9d05fe17add13876"
+  integrity sha512-SFxgwYmZ3HZPyZwJRiVNLRHWuW2OgE5k2nrVs6D9Iv4PPnXVffuEHy83Sfx/l4SqF+5kyJXjAyUmrG7tNm+qVg==
+  dependencies:
+    "@babel/types" "^7.10.1"
+
 "@babel/helper-module-imports@^7.8.3":
   version "7.8.3"
   resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.8.3.tgz#7fe39589b39c016331b6b8c3f441e8f0b1419498"
@@ -164,6 +195,11 @@
   resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz#9ea293be19babc0f52ff8ca88b34c3611b208670"
   integrity sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==
 
+"@babel/helper-plugin-utils@^7.10.1":
+  version "7.10.1"
+  resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.1.tgz#ec5a5cf0eec925b66c60580328b122c01230a127"
+  integrity sha512-fvoGeXt0bJc7VMWZGCAEBEMo/HAjW2mP8apF5eXK0wSqwLAVHAISCWRoLMBMUs2kqeaG77jltVqu4Hn8Egl3nA==
+
 "@babel/helper-regex@^7.8.3":
   version "7.8.3"
   resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.8.3.tgz#139772607d51b93f23effe72105b319d2a4c6965"
@@ -207,6 +243,11 @@
   dependencies:
     "@babel/types" "^7.8.3"
 
+"@babel/helper-validator-identifier@^7.10.1":
+  version "7.10.1"
+  resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.1.tgz#5770b0c1a826c4f53f5ede5e153163e0318e94b5"
+  integrity sha512-5vW/JXLALhczRCWP0PnFDMCJAchlBvM7f4uk/jXritBnIa6E1KmqmtrS3yn1LAnxFBypQ3eneLuXjsnfQsgILw==
+
 "@babel/helper-validator-identifier@^7.9.0", "@babel/helper-validator-identifier@^7.9.5":
   version "7.9.5"
   resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz#90977a8e6fbf6b431a7dc31752eee233bf052d80"
@@ -340,6 +381,13 @@
   dependencies:
     "@babel/helper-plugin-utils" "^7.8.0"
 
+"@babel/plugin-syntax-jsx@^7.10.1":
+  version "7.10.1"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.10.1.tgz#0ae371134a42b91d5418feb3c8c8d43e1565d2da"
+  integrity sha512-+OxyOArpVFXQeXKLO9o+r2I4dIoVoy6+Uu0vKELrlweDM3QJADZj+Z+5ERansZqIZBcLj42vHnDI8Rz9BnRIuQ==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.10.1"
+
 "@babel/plugin-syntax-nullish-coalescing-operator@^7.8.0":
   version "7.8.3"
   resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9"
@@ -567,6 +615,56 @@
   dependencies:
     "@babel/helper-plugin-utils" "^7.8.3"
 
+"@babel/plugin-transform-react-display-name@^7.10.1":
+  version "7.10.1"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.10.1.tgz#e6a33f6d48dfb213dda5e007d0c7ff82b6a3d8ef"
+  integrity sha512-rBjKcVwjk26H3VX8pavMxGf33LNlbocMHdSeldIEswtQ/hrjyTG8fKKILW1cSkODyRovckN/uZlGb2+sAV9JUQ==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.10.1"
+
+"@babel/plugin-transform-react-jsx-development@^7.10.1":
+  version "7.10.1"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.10.1.tgz#1ac6300d8b28ef381ee48e6fec430cc38047b7f3"
+  integrity sha512-XwDy/FFoCfw9wGFtdn5Z+dHh6HXKHkC6DwKNWpN74VWinUagZfDcEJc3Y8Dn5B3WMVnAllX8Kviaw7MtC5Epwg==
+  dependencies:
+    "@babel/helper-builder-react-jsx-experimental" "^7.10.1"
+    "@babel/helper-plugin-utils" "^7.10.1"
+    "@babel/plugin-syntax-jsx" "^7.10.1"
+
+"@babel/plugin-transform-react-jsx-self@^7.10.1":
+  version "7.10.1"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.10.1.tgz#22143e14388d72eb88649606bb9e46f421bc3821"
+  integrity sha512-4p+RBw9d1qV4S749J42ZooeQaBomFPrSxa9JONLHJ1TxCBo3TzJ79vtmG2S2erUT8PDDrPdw4ZbXGr2/1+dILA==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.10.1"
+    "@babel/plugin-syntax-jsx" "^7.10.1"
+
+"@babel/plugin-transform-react-jsx-source@^7.10.1":
+  version "7.10.1"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.10.1.tgz#30db3d4ee3cdebbb26a82a9703673714777a4273"
+  integrity sha512-neAbaKkoiL+LXYbGDvh6PjPG+YeA67OsZlE78u50xbWh2L1/C81uHiNP5d1fw+uqUIoiNdCC8ZB+G4Zh3hShJA==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.10.1"
+    "@babel/plugin-syntax-jsx" "^7.10.1"
+
+"@babel/plugin-transform-react-jsx@^7.10.1", "@babel/plugin-transform-react-jsx@^7.9.4":
+  version "7.10.1"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.10.1.tgz#91f544248ba131486decb5d9806da6a6e19a2896"
+  integrity sha512-MBVworWiSRBap3Vs39eHt+6pJuLUAaK4oxGc8g+wY+vuSJvLiEQjW1LSTqKb8OUPtDvHCkdPhk7d6sjC19xyFw==
+  dependencies:
+    "@babel/helper-builder-react-jsx" "^7.10.1"
+    "@babel/helper-builder-react-jsx-experimental" "^7.10.1"
+    "@babel/helper-plugin-utils" "^7.10.1"
+    "@babel/plugin-syntax-jsx" "^7.10.1"
+
+"@babel/plugin-transform-react-pure-annotations@^7.10.1":
+  version "7.10.1"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.10.1.tgz#f5e7c755d3e7614d4c926e144f501648a5277b70"
+  integrity sha512-mfhoiai083AkeewsBHUpaS/FM1dmUENHBMpS/tugSJ7VXqXO5dCN1Gkint2YvM1Cdv1uhmAKt1ZOuAjceKmlLA==
+  dependencies:
+    "@babel/helper-annotate-as-pure" "^7.10.1"
+    "@babel/helper-plugin-utils" "^7.10.1"
+
 "@babel/plugin-transform-regenerator@^7.8.7":
   version "7.8.7"
   resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.8.7.tgz#5e46a0dca2bee1ad8285eb0527e6abc9c37672f8"
@@ -703,6 +801,19 @@
     "@babel/types" "^7.4.4"
     esutils "^2.0.2"
 
+"@babel/preset-react@^7.9.4":
+  version "7.10.1"
+  resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.10.1.tgz#e2ab8ae9a363ec307b936589f07ed753192de041"
+  integrity sha512-Rw0SxQ7VKhObmFjD/cUcKhPTtzpeviEFX1E6PgP+cYOhQ98icNqtINNFANlsdbQHrmeWnqdxA4Tmnl1jy5tp3Q==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.10.1"
+    "@babel/plugin-transform-react-display-name" "^7.10.1"
+    "@babel/plugin-transform-react-jsx" "^7.10.1"
+    "@babel/plugin-transform-react-jsx-development" "^7.10.1"
+    "@babel/plugin-transform-react-jsx-self" "^7.10.1"
+    "@babel/plugin-transform-react-jsx-source" "^7.10.1"
+    "@babel/plugin-transform-react-pure-annotations" "^7.10.1"
+
 "@babel/runtime@^7.8.4":
   version "7.9.6"
   resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.9.6.tgz#a9102eb5cadedf3f31d08a9ecf294af7827ea29f"
@@ -734,6 +845,15 @@
     globals "^11.1.0"
     lodash "^4.17.13"
 
+"@babel/types@^7.10.1":
+  version "7.10.2"
+  resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.10.2.tgz#30283be31cad0dbf6fb00bd40641ca0ea675172d"
+  integrity sha512-AD3AwWBSz0AWF0AkCN9VPiWrvldXq+/e3cHa4J89vo4ymjz1XwrBFFVZmkJTsQIPNk+ZVomPSXUJqq8yyjZsng==
+  dependencies:
+    "@babel/helper-validator-identifier" "^7.10.1"
+    lodash "^4.17.13"
+    to-fast-properties "^2.0.0"
+
 "@babel/types@^7.4.4", "@babel/types@^7.8.3", "@babel/types@^7.8.6", "@babel/types@^7.9.0", "@babel/types@^7.9.5", "@babel/types@^7.9.6":
   version "7.9.6"
   resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.9.6.tgz#2c5502b427251e9de1bd2dff95add646d95cc9f7"
@@ -1281,6 +1401,11 @@ combine-source-map@^0.8.0, combine-source-map@~0.8.0:
     lodash.memoize "~3.0.3"
     source-map "~0.5.3"
 
+commander@~2.20.3:
+  version "2.20.3"
+  resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
+  integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
+
 component-emitter@^1.2.1:
   version "1.3.0"
   resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0"
@@ -2256,7 +2381,7 @@ lodash@^4.17.13:
   resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
   integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
 
-loose-envify@^1.0.0:
+loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0:
   version "1.4.0"
   resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
   integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
@@ -2726,6 +2851,15 @@ process@~0.11.0:
   resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
   integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI=
 
+prop-types@^15.6.2:
+  version "15.7.2"
+  resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
+  integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==
+  dependencies:
+    loose-envify "^1.4.0"
+    object-assign "^4.1.1"
+    react-is "^16.8.1"
+
 public-encrypt@^4.0.0:
   version "4.0.3"
   resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0"
@@ -2786,6 +2920,30 @@ range-parser@~1.2.1:
   resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031"
   integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==
 
+react-dom@^16.13.1:
+  version "16.13.1"
+  resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.13.1.tgz#c1bd37331a0486c078ee54c4740720993b2e0e7f"
+  integrity sha512-81PIMmVLnCNLO/fFOQxdQkvEq/+Hfpv24XNJfpyZhTRfO0QcmQIF/PgCa1zCOj2w1hrn12MFLyaJ/G0+Mxtfag==
+  dependencies:
+    loose-envify "^1.1.0"
+    object-assign "^4.1.1"
+    prop-types "^15.6.2"
+    scheduler "^0.19.1"
+
+react-is@^16.8.1:
+  version "16.13.1"
+  resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
+  integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
+
+react@^16.13.1:
+  version "16.13.1"
+  resolved "https://registry.yarnpkg.com/react/-/react-16.13.1.tgz#2e818822f1a9743122c063d6410d85c1e3afe48e"
+  integrity sha512-YMZQQq32xHLX0bz5Mnibv1/LHb3Sqzngu7xstSM+vrkE5Kzr9xE0yMByK5kMoTK30YVJE61WfbxIFFvfeDKT1w==
+  dependencies:
+    loose-envify "^1.1.0"
+    object-assign "^4.1.1"
+    prop-types "^15.6.2"
+
 read-only-stream@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/read-only-stream/-/read-only-stream-2.0.0.tgz#2724fd6a8113d73764ac288d4386270c1dbf17f0"
@@ -2973,6 +3131,14 @@ safe-regex@^1.1.0:
   dependencies:
     ret "~0.1.10"
 
+scheduler@^0.19.1:
+  version "0.19.1"
+  resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.19.1.tgz#4f3e2ed2c1a7d65681f4c854fa8c5a1ccb40f196"
+  integrity sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==
+  dependencies:
+    loose-envify "^1.1.0"
+    object-assign "^4.1.1"
+
 semver@7.0.0:
   version "7.0.0"
   resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e"
@@ -3363,6 +3529,13 @@ typedarray@^0.0.6:
   resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
   integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
 
+uglify-js@^3.9.3:
+  version "3.9.4"
+  resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.9.4.tgz#867402377e043c1fc7b102253a22b64e5862401b"
+  integrity sha512-8RZBJq5smLOa7KslsNsVcSH+KOXf1uDU8yqLeNuVKwmT0T3FA0ZoXlinQfRad7SDcbZZRZE4ov+2v71EnxNyCA==
+  dependencies:
+    commander "~2.20.3"
+
 umd@^3.0.0:
   version "3.0.3"
   resolved "https://registry.yarnpkg.com/umd/-/umd-3.0.3.tgz#aa9fe653c42b9097678489c01000acb69f0b26cf"