diff --git a/Dockerfile b/Dockerfile
index 9a8de3d97..9a8d4f1c0 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,7 +1,10 @@
 # building frontend
 FROM node:13.1 as build-deps
 COPY web ./
+# fix docker not following symlinks
+COPY doc/getting-started.md ./src/assets/
 RUN yarn install
+RUN yarn lint
 RUN yarn build
 
 # production
diff --git a/backend/README.md b/backend/README.md
index c2d22bafc..1d202e003 100644
--- a/backend/README.md
+++ b/backend/README.md
@@ -18,28 +18,4 @@ pipenv install
 
 ## Usage
 
-### Add documentation
-
-You can uppload any static html site by zipping it and 
-then posting the file to the backend. 
-
-For example to upload the file `docs.zip` as version `1.0.0` for awesome-project.
-
-```sh
-curl -X POST -F "file=@docs.zip" http://localhost:5000/api/awesome-project/1.0.0
-```
-
-Any other file type is uploaded as well. 
-An uploaded pdf would be available as 
-`http://localhost:5000/api/awesome-project/1.0.0/my_awesome.pdf` 
-
-### Tag documentation
-
-After this you can tag a version, this can be usefull when
-the latest version should be available as `http://localhost:5000/docs/awesome-project/latest`
-
-If you want to tag the version `1.0.0` as `latest` for awesome-project.
-
-```sh
-curl -X PUT http://localhost:5000/api/awesome-project/1.0.0/tags/latest
-```
+See [Help.md](Help.md)
diff --git a/doc/getting-started.md b/doc/getting-started.md
new file mode 100644
index 000000000..5ca8969f9
--- /dev/null
+++ b/doc/getting-started.md
@@ -0,0 +1,31 @@
+## Getting started with DOCAT
+
+### Upload your documentation
+
+You can upload any static html site by zipping it and
+then posting the file to the backend.
+
+For example to upload the file `docs.zip` as version `1.0.0` for `awesome-project`.
+
+```sh
+curl -X POST -F "file=@docs.zip" http://localhost:8000/api/awesome-project/1.0.0
+```
+
+Any other file type is uploaded as well.
+An uploaded pdf could be viewed like this:
+
+`http://localhost/#/awesome-project/1.0.0/my_awesome.pdf`
+
+You can also manually upload your documentation.
+A very simple web form can be found under [upload](#/upload).
+
+### Tag documentation
+
+After this you can tag a version, this can be usefull when
+the latest version should be available as `http://localhost:5000/docs/awesome-project/latest`
+
+If you want to tag the version `1.0.0` as `latest` for awesome-project.
+
+```sh
+curl -X PUT http://localhost:5000/api/awesome-project/1.0.0/tags/latest
+```
diff --git a/web/package.json b/web/package.json
index 61760c38b..46637b142 100644
--- a/web/package.json
+++ b/web/package.json
@@ -8,10 +8,14 @@
     "lint": "vue-cli-service lint"
   },
   "dependencies": {
+    "babel-runtime": "^6.26.0",
     "core-js": "^3.3.2",
+    "html-loader": "^0.5.5",
     "node-sass": "^4.13.0",
     "sass-loader": "^8.0.0",
-    "vue": "^2.6.10"
+    "vue": "^2.6.10",
+    "vue-markdown": "^2.2.4",
+    "vuelidate": "^0.7.4"
   },
   "devDependencies": {
     "@vue/cli-plugin-babel": "^4.0.0",
diff --git a/web/public/index.html b/web/public/index.html
index f22e18b2d..44d256ba5 100644
--- a/web/public/index.html
+++ b/web/public/index.html
@@ -5,6 +5,7 @@
     <meta http-equiv="X-UA-Compatible" content="IE=edge">
     <meta name="viewport" content="width=device-width,initial-scale=1.0">
     <link rel="icon" href="<%= BASE_URL %>favicon.ico">
+    <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
     <title>docat</title>
   </head>
   <body>
diff --git a/web/src/assets/getting-started.md b/web/src/assets/getting-started.md
new file mode 120000
index 000000000..8026b1c94
--- /dev/null
+++ b/web/src/assets/getting-started.md
@@ -0,0 +1 @@
+../../../doc/getting-started.md
\ No newline at end of file
diff --git a/web/src/components/Help.vue b/web/src/components/Help.vue
new file mode 100644
index 000000000..05a29ab14
--- /dev/null
+++ b/web/src/components/Help.vue
@@ -0,0 +1,23 @@
+<template>
+  <vue-markdown>
+    {{ help }}
+  </vue-markdown>
+</template>
+
+<script>
+import VueMarkdown from 'vue-markdown'
+
+import help from '@/assets/getting-started.md'
+
+export default {
+  name: 'help',
+  components: {
+    VueMarkdown
+  },
+  data() {
+    return {
+      help,
+    }
+  }
+}
+</script>
diff --git a/web/src/components/Layout.vue b/web/src/components/Layout.vue
index 881be7596..d33db7f1d 100644
--- a/web/src/components/Layout.vue
+++ b/web/src/components/Layout.vue
@@ -18,6 +18,9 @@
         <div v-if="!fullscreen" class="md-layout-item md-size-15 md-small-hide"></div>
         <div class="md-layout-item">
           <slot></slot>
+          <div class="help">
+            <router-link to="/help" v-if="!fullscreen">help</router-link>
+          </div>
         </div>
         <div v-if="!fullscreen" class="md-layout-item md-size-15 md-small-hide"></div>
       </div>
@@ -66,4 +69,19 @@ body,
   height: 100%;
 }
 
+a {
+  /* TODO: remove hack */
+  color: #742a47 !important;
+}
+
+.help {
+  width: 100%;
+  border-top: 1px solid #e8e8e8;
+  padding-top: 16px;
+  margin-top: 16px;
+
+  a {
+    margin-left: 50%;
+  }
+}
 </style>
\ No newline at end of file
diff --git a/web/src/components/ProjectOverview.vue b/web/src/components/ProjectOverview.vue
index 870bc7a78..1935d76ae 100644
--- a/web/src/components/ProjectOverview.vue
+++ b/web/src/components/ProjectOverview.vue
@@ -6,17 +6,21 @@
       v-bind:key="project.name"
       :project="project.name"
     />
+    <Help v-if="!projects.length" />
   </div>
 </template>
 
 <script>
+import Help from '@/components/Help.vue'
 import Project from '@/components/Project.vue'
+
 import ProjectRepository from '@/repositories/ProjectRepository'
 
 export default {
   name: 'ProjectOverview',
   components: {
-    Project
+    Project,
+    Help
   },
   data() {
     return {
diff --git a/web/src/components/UploadButton.vue b/web/src/components/UploadButton.vue
new file mode 100644
index 000000000..302155a1e
--- /dev/null
+++ b/web/src/components/UploadButton.vue
@@ -0,0 +1,14 @@
+<template>
+  <md-button to="/upload" class="md-fab md-primary">
+    <md-icon>backup</md-icon>
+    <md-tooltip md-direction="left">upload documentation</md-tooltip>
+  </md-button>
+</template>
+
+<script>
+export default {
+  name: 'UploadButton'
+}
+</script>
+
+
diff --git a/web/src/main.js b/web/src/main.js
index cd276916b..888835f12 100644
--- a/web/src/main.js
+++ b/web/src/main.js
@@ -4,13 +4,18 @@ import App from '@/App.vue'
 // configure vue material (https://vuematerial.io/getting-started/)
 import {
   MdCard,
+  MdButton,
   MdAvatar,
   MdApp,
   MdToolbar,
   MdContent,
   MdList,
   MdField,
-  MdMenu
+  MdMenu,
+  MdProgress,
+  MdSnackbar,
+  MdIcon,
+  MdTooltip
 } from 'vue-material/dist/components'
 import 'vue-material/dist/vue-material.min.css'
 import 'vue-material/dist/theme/default.css'
@@ -23,6 +28,16 @@ Vue.use(MdList)
 Vue.use(MdToolbar)
 Vue.use(MdCard)
 Vue.use(MdAvatar)
+Vue.use(MdProgress)
+Vue.use(MdSnackbar)
+Vue.use(MdButton)
+Vue.use(MdIcon)
+Vue.use(MdTooltip)
+
+// configure to use vue-markdown (https://github.com/miaolz123/vue-markdown)
+import VueMarkdown from 'vue-markdown'
+
+Vue.use(VueMarkdown);
 
 // configure vue router (https://router.vuejs.org/installation.html)
 import VueRouter from 'vue-router'
@@ -32,10 +47,14 @@ Vue.use(VueRouter)
 // configure the app's routing
 import Home from '@/pages/Home.vue'
 import Docs from '@/pages/Docs.vue'
+import Help from '@/pages/Help.vue'
+import Upload from '@/pages/Upload.vue'
 
 const routes = [
   { path: '/', component: Home },
-  { path: '/:project/:version/:location?', component: Docs }
+  { path: '/:project/:version/:location?', component: Docs },
+  { path: '/help', component: Help },
+  { path: '/upload', component: Upload },
 ]
 
 const router = new VueRouter({
diff --git a/web/src/pages/Help.vue b/web/src/pages/Help.vue
new file mode 100644
index 000000000..fe30dfec9
--- /dev/null
+++ b/web/src/pages/Help.vue
@@ -0,0 +1,23 @@
+<template>
+  <div>
+    <Layout>
+      <Help class="spacing" />
+    </Layout>
+    <UploadButton class="upload-button" />
+  </div>
+</template>
+
+<script>
+import Layout from '@/components/Layout.vue'
+import Help from '@/components/Help.vue'
+import UploadButton from '@/components/UploadButton.vue'
+
+export default {
+  name: 'help-page',
+  components: {
+    Layout,
+    Help,
+    UploadButton
+  }
+}
+</script>
\ No newline at end of file
diff --git a/web/src/pages/Home.vue b/web/src/pages/Home.vue
index 678432c5d..d8760f07d 100644
--- a/web/src/pages/Home.vue
+++ b/web/src/pages/Home.vue
@@ -1,18 +1,23 @@
 <template>
-  <Layout>
-    <ProjectOverview class="spacing" />
-  </Layout>
+  <div>
+    <Layout>
+      <ProjectOverview class="spacing" />
+    </Layout>
+    <UploadButton class="upload-button" />
+  </div>
 </template>
 
 <script>
 import ProjectOverview from '@/components/ProjectOverview.vue'
 import Layout from '@/components/Layout.vue'
+import UploadButton from '@/components/UploadButton.vue'
 
 export default {
   name: 'home',
   components: {
     ProjectOverview,
-    Layout
+    Layout,
+    UploadButton
   }
 }
 </script>
@@ -30,4 +35,20 @@ export default {
 .spacing {
   padding-top: 20px;
 }
+
+.upload-button {
+  position: fixed;
+  bottom: 16px;
+}
+
+@media all and (max-width: 959px) {
+  .upload-button {
+    right: 16px;
+  }
+}
+@media all and (min-width: 959px) {
+  .upload-button {
+    right: 15%;
+  }
+}
 </style>
diff --git a/web/src/pages/Upload.vue b/web/src/pages/Upload.vue
new file mode 100644
index 000000000..02ad55415
--- /dev/null
+++ b/web/src/pages/Upload.vue
@@ -0,0 +1,131 @@
+<template>
+   <Layout>
+    <form novalidate @submit.prevent="validateUpload" class="upload-form">
+      <h1 class="upload-title">Upload documentation</h1>
+
+      <p>
+        If you want to automate the upload of your documentation consider using <code>curl</code>
+        to post it to the server.
+        There are some examples in the <a href="https://github.com/randombenj/docat/" target="_blank">docat repository</a>.
+      </p>
+
+      <md-field :class="getValidationClass('project')">
+        <label>Projectname</label>
+        <md-input type="text" id="project" name="project" v-model="form.project" :disabled="sending" />
+        <span class="md-error" v-if="!$v.form.project.required">The projectname is required</span>
+      </md-field>
+
+      <md-field :class="getValidationClass('version')">
+        <label>Version</label>
+        <md-input type="text" id="version" name="version" v-model="form.version" :disabled="sending" />
+        <span class="md-error" v-if="!$v.form.version.required">The version is required</span>
+      </md-field>
+
+      <md-field :class="getValidationClass('documentation')">
+        <label >Documentation (zip file)</label>
+        <md-file id="documentation" @change="onFileUpload($event)" :disabled="sending" accept="zip,application/octet-stream,application/zip,application/x-zip,application/x-zip-compressed" />
+        <span class="md-error">The documentation is required</span>
+      </md-field>
+
+      <md-progress-bar md-mode="indeterminate" class="md-accent" v-if="sending" />
+      <button class="md-button md-raised md-primary" :disabled="sending" type="submit">Upload</button>
+
+      <md-snackbar md-position="left" :md-duration="4000" :md-active.sync="showError" md-persistent>
+        <span>{{ error }}</span>
+        <md-button class="md-primary" @click="showError = false">Close</md-button>
+      </md-snackbar>
+    </form>
+  </Layout>
+</template>
+
+<script>
+import { validationMixin } from 'vuelidate'
+import { required } from 'vuelidate/lib/validators'
+
+import Layout from '@/components/Layout.vue'
+import ProjectRepository from '@/repositories/ProjectRepository'
+
+export default {
+  name: 'Upload',
+  mixins: [validationMixin],
+  components: {
+    Layout,
+  },
+  data() {
+    return {
+      form: {
+        project: null,
+        version: null
+      },
+      sending: false,
+      error: '',
+      showError: false
+    }
+  },
+  validations: {
+    form: {
+      project: { required },
+      version: { required },
+      file: ''
+    }
+  },
+  methods: {
+    async upload() {
+      this.sending = true
+      const formData = new FormData()
+      formData.append("file", this.form.file)
+
+      try {
+        await ProjectRepository.upload(this.form.project, this.form.version, formData)
+        this.clearForm()
+      } catch(err) {
+        // something went wrong while
+        this.showError = true
+        this.error = err
+      }
+
+      this.sending = false
+    },
+    onFileUpload(e) {
+      const files = e.target.files || e.dataTransfer.files
+
+      if (files.length) {
+        this.form.file = files[0]
+      }
+    },
+    getValidationClass(fieldName) {
+      const field = this.$v.form[fieldName]
+
+      if (field) {
+        return {
+          'md-invalid': field.$invalid && field.$dirty
+        }
+      }
+    },
+    clearForm () {
+      this.$v.$reset()
+      this.form.project = null
+      this.form.version = null
+    },
+    validateUpload() {
+      this.$v.$touch()
+
+      if (!this.$v.$invalid) {
+        this.upload()
+      }
+    }
+  }
+}
+</script>
+
+<style scoped>
+.upload-title {
+  margin-bottom: 16px;
+}
+
+.upload-form {
+  margin-top: 48px;
+  padding-right: 16px;
+  padding-left: 16px;
+}
+</style>
\ No newline at end of file
diff --git a/web/src/repositories/ProjectRepository.js b/web/src/repositories/ProjectRepository.js
index 604dbe4b8..286b89d61 100644
--- a/web/src/repositories/ProjectRepository.js
+++ b/web/src/repositories/ProjectRepository.js
@@ -36,5 +36,13 @@ export default {
     return (await Repository.get(`${Repository.defaults.baseURL}/${resource}/${projectName}/`))
       .data
       .filter((version) => version.type == 'directory')
+  },
+
+  async upload(projectName, version, formData) {
+    await Repository.post(
+      `${Repository.defaults.baseURL}/api/${projectName}/${version}`,
+      formData,
+      { headers: { 'Content-Type': 'multipart/form-data' } }
+    )
   }
 }
diff --git a/web/vue.config.js b/web/vue.config.js
new file mode 100644
index 000000000..aae1b69bd
--- /dev/null
+++ b/web/vue.config.js
@@ -0,0 +1,10 @@
+module.exports = {
+  configureWebpack: {
+    module: {
+      rules: [{
+        test: /\.md$/,
+        use: [{ loader: "html-loader" }]
+      }]
+    }
+  }
+}
\ No newline at end of file
diff --git a/web/yarn.lock b/web/yarn.lock
index 0407d2b6a..9f3f3b9c9 100644
--- a/web/yarn.lock
+++ b/web/yarn.lock
@@ -1433,6 +1433,11 @@ assign-symbols@^1.0.0:
   resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367"
   integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=
 
+ast-types@0.9.6:
+  version "0.9.6"
+  resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.9.6.tgz#102c9e9e9005d3e7e3829bf0c4fa24ee862ee9b9"
+  integrity sha1-ECyenpAF0+fjgpvwxPok7oYu6bk=
+
 astral-regex@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9"
@@ -1541,6 +1546,14 @@ babel-plugin-module-resolver@^3.2.0:
     reselect "^3.0.1"
     resolve "^1.4.0"
 
+babel-runtime@^6.26.0:
+  version "6.26.0"
+  resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe"
+  integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4=
+  dependencies:
+    core-js "^2.4.0"
+    regenerator-runtime "^0.11.0"
+
 balanced-match@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
@@ -2122,6 +2135,11 @@ clone@^1.0.2:
   resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e"
   integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4=
 
+clone@^2.1.0:
+  version "2.1.2"
+  resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f"
+  integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=
+
 coa@^2.0.2:
   version "2.0.2"
   resolved "https://registry.yarnpkg.com/coa/-/coa-2.0.2.tgz#43f6c21151b4ef2bf57187db0d73de229e3e7ec3"
@@ -2348,6 +2366,11 @@ core-js-pure@^3.0.0:
   resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.4.0.tgz#a0e89ce3f8142512b784a3c9f85839730acd8203"
   integrity sha512-d49s6GiW3ePYM8vCglfLLo6bueYx+Sff6MYtjohTMSB0AoxVfABXMUSmYHtKAEvW77T9JTKMyHrhE20nZ8gYDA==
 
+core-js@^2.4.0:
+  version "2.6.10"
+  resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.10.tgz#8a5b8391f8cc7013da703411ce5b585706300d7f"
+  integrity sha512-I39t74+4t+zau64EN1fE5v2W31Adtc/REhzWN+gWRRXg6WH5qAsZm62DHpQ1+Yhe4047T55jvzz7MUqF/dBBlA==
+
 core-js@^3.3.2:
   version "3.4.0"
   resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.4.0.tgz#29ea478601789c72f2978e9bb98f43546f89d3aa"
@@ -3008,7 +3031,7 @@ enhanced-resolve@^4.1.0:
     memory-fs "^0.5.0"
     tapable "^1.0.0"
 
-entities@^1.1.1:
+entities@^1.1.1, entities@~1.1.1:
   version "1.1.2"
   resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56"
   integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==
@@ -3064,6 +3087,14 @@ es-to-primitive@^1.2.0:
     is-date-object "^1.0.1"
     is-symbol "^1.0.2"
 
+es6-templates@^0.2.3:
+  version "0.2.3"
+  resolved "https://registry.yarnpkg.com/es6-templates/-/es6-templates-0.2.3.tgz#5cb9ac9fb1ded6eb1239342b81d792bbb4078ee4"
+  integrity sha1-XLmsn7He1usSOTQrgdeSu7QHjuQ=
+  dependencies:
+    recast "~0.11.12"
+    through "~2.3.6"
+
 escape-html@~1.0.3:
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
@@ -3177,6 +3208,11 @@ esprima@^4.0.0:
   resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
   integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
 
+esprima@~3.1.0:
+  version "3.1.3"
+  resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633"
+  integrity sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=
+
 esquery@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.1.tgz#406c51658b1f5991a5f9b62b1dc25b00e3e5c708"
@@ -3407,6 +3443,11 @@ fast-levenshtein@~2.0.6:
   resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
   integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=
 
+fastparse@^1.1.1:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.2.tgz#91728c5a5942eced8531283c79441ee4122c35a9"
+  integrity sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==
+
 faye-websocket@^0.10.0:
   version "0.10.0"
   resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.10.0.tgz#4e492f8d04dfb6f89003507f6edbf2d501e7c6f4"
@@ -3952,7 +3993,7 @@ hex-color-regex@^1.1.0:
   resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e"
   integrity sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==
 
-highlight.js@^9.6.0:
+highlight.js@^9.12.0, highlight.js@^9.6.0:
   version "9.16.2"
   resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.16.2.tgz#68368d039ffe1c6211bcc07e483daf95de3e403e"
   integrity sha512-feMUrVLZvjy0oC7FVJQcSQRqbBq9kwqnYE4+Kj9ZjbHh3g+BisiPgF49NyQbVLNdrL/qqZr3Ca9yOKwgn2i/tw==
@@ -4006,7 +4047,18 @@ html-entities@^1.2.1:
   resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.2.1.tgz#0df29351f0721163515dfb9e5543e5f6eed5162f"
   integrity sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=
 
-html-minifier@^3.2.3:
+html-loader@^0.5.5:
+  version "0.5.5"
+  resolved "https://registry.yarnpkg.com/html-loader/-/html-loader-0.5.5.tgz#6356dbeb0c49756d8ebd5ca327f16ff06ab5faea"
+  integrity sha512-7hIW7YinOYUpo//kSYcPB6dCKoceKLmOwjEMmhIobHuWGDVl0Nwe4l68mdG/Ru0wcUxQjVMEoZpkalZ/SE7zog==
+  dependencies:
+    es6-templates "^0.2.3"
+    fastparse "^1.1.1"
+    html-minifier "^3.5.8"
+    loader-utils "^1.1.0"
+    object-assign "^4.1.1"
+
+html-minifier@^3.2.3, html-minifier@^3.5.8:
   version "3.5.21"
   resolved "https://registry.yarnpkg.com/html-minifier/-/html-minifier-3.5.21.tgz#d0040e054730e354db008463593194015212d20c"
   integrity sha512-LKUKwuJDhxNa3uf/LPR/KVjm/l3rBqtYeCOAekvG8F1vItxMUpueGd94i/asDDr8/1u7InxzFA5EeGjhhG5mMA==
@@ -4764,6 +4816,13 @@ jsprim@^1.2.2:
     json-schema "0.2.3"
     verror "1.10.0"
 
+katex@^0.6.0:
+  version "0.6.0"
+  resolved "https://registry.yarnpkg.com/katex/-/katex-0.6.0.tgz#12418e09121c05c92041b6b3b9fb6bab213cb6f3"
+  integrity sha1-EkGOCRIcBckgQbazuftrqyE8tvM=
+  dependencies:
+    match-at "^0.1.0"
+
 killable@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.1.tgz#4c8ce441187a061c7474fb87ca08e2a638194892"
@@ -4835,6 +4894,13 @@ lines-and-columns@^1.1.6:
   resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00"
   integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=
 
+linkify-it@~1.2.2:
+  version "1.2.4"
+  resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-1.2.4.tgz#0773526c317c8fd13bd534ee1d180ff88abf881a"
+  integrity sha1-B3NSbDF8j9E71TTuHRgP+Iq/iBo=
+  dependencies:
+    uc.micro "^1.0.1"
+
 load-json-file@^1.0.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0"
@@ -5027,6 +5093,82 @@ map-visit@^1.0.0:
   dependencies:
     object-visit "^1.0.0"
 
+markdown-it-abbr@^1.0.3:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/markdown-it-abbr/-/markdown-it-abbr-1.0.4.tgz#d66b5364521cbb3dd8aa59dadfba2fb6865c8fd8"
+  integrity sha1-1mtTZFIcuz3Yqlna37ovtoZcj9g=
+
+markdown-it-deflist@^2.0.1:
+  version "2.0.3"
+  resolved "https://registry.yarnpkg.com/markdown-it-deflist/-/markdown-it-deflist-2.0.3.tgz#5727db04184d3cb2bc6ee4a9641e3a1091d5fd6f"
+  integrity sha512-/BNZ8ksW42bflm1qQLnRI09oqU2847Z7MVavrR0MORyKLtiUYOMpwtlAfMSZAQU9UCvaUZMpgVAqoS3vpToJxw==
+
+markdown-it-emoji@^1.1.1:
+  version "1.4.0"
+  resolved "https://registry.yarnpkg.com/markdown-it-emoji/-/markdown-it-emoji-1.4.0.tgz#9bee0e9a990a963ba96df6980c4fddb05dfb4dcc"
+  integrity sha1-m+4OmpkKljupbfaYDE/dsF37Tcw=
+
+markdown-it-footnote@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/markdown-it-footnote/-/markdown-it-footnote-2.0.0.tgz#14e9c4f68ff12cf354fa365ae378276e8104ca94"
+  integrity sha1-FOnE9o/xLPNU+jZa43gnboEEypQ=
+
+markdown-it-ins@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/markdown-it-ins/-/markdown-it-ins-2.0.0.tgz#a5aa6a30f1e2f71e9497567cfdff40f1fde67483"
+  integrity sha1-papqMPHi9x6Ul1Z8/f9A8f3mdIM=
+
+markdown-it-katex@^2.0.3:
+  version "2.0.3"
+  resolved "https://registry.yarnpkg.com/markdown-it-katex/-/markdown-it-katex-2.0.3.tgz#d7b86a1aea0b9d6496fab4e7919a18fdef589c39"
+  integrity sha1-17hqGuoLnWSW+rTnkZoY/e9YnDk=
+  dependencies:
+    katex "^0.6.0"
+
+markdown-it-mark@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/markdown-it-mark/-/markdown-it-mark-2.0.0.tgz#46a1aa947105aed8188978e0a016179e404f42c7"
+  integrity sha1-RqGqlHEFrtgYiXjgoBYXnkBPQsc=
+
+markdown-it-sub@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/markdown-it-sub/-/markdown-it-sub-1.0.0.tgz#375fd6026eae7ddcb012497f6411195ea1e3afe8"
+  integrity sha1-N1/WAm6ufdywEkl/ZBEZXqHjr+g=
+
+markdown-it-sup@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/markdown-it-sup/-/markdown-it-sup-1.0.0.tgz#cb9c9ff91a5255ac08f3fd3d63286e15df0a1fc3"
+  integrity sha1-y5yf+RpSVawI8/09YyhuFd8KH8M=
+
+markdown-it-task-lists@^2.0.1:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/markdown-it-task-lists/-/markdown-it-task-lists-2.1.1.tgz#f68f4d2ac2bad5a2c373ba93081a1a6848417088"
+  integrity sha512-TxFAc76Jnhb2OUu+n3yz9RMu4CwGfaT788br6HhEDlvWfdeJcLUsxk1Hgw2yJio0OXsxv7pyIPmvECY7bMbluA==
+
+markdown-it-toc-and-anchor@^4.1.2:
+  version "4.2.0"
+  resolved "https://registry.yarnpkg.com/markdown-it-toc-and-anchor/-/markdown-it-toc-and-anchor-4.2.0.tgz#d1613327cc63c61f82cd66cbac5564f4db12c0e9"
+  integrity sha512-DusSbKtg8CwZ92ztN7bOojDpP4h0+w7BVOPuA3PHDIaabMsERYpwsazLYSP/UlKedoQjOz21mwlai36TQ04EpA==
+  dependencies:
+    clone "^2.1.0"
+    uslug "^1.0.4"
+
+markdown-it@^6.0.1:
+  version "6.1.1"
+  resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-6.1.1.tgz#ced037f4473ee9f5153ac414f77dc83c91ba927c"
+  integrity sha1-ztA39Ec+6fUVOsQU933IPJG6knw=
+  dependencies:
+    argparse "^1.0.7"
+    entities "~1.1.1"
+    linkify-it "~1.2.2"
+    mdurl "~1.0.1"
+    uc.micro "^1.0.1"
+
+match-at@^0.1.0:
+  version "0.1.1"
+  resolved "https://registry.yarnpkg.com/match-at/-/match-at-0.1.1.tgz#25d040d291777704d5e6556bbb79230ec2de0540"
+  integrity sha512-h4Yd392z9mST+dzc+yjuybOGFNOZjmXIPKWjxBd1Bb23r4SmDOsk2NYCU2BMUBGbSpZqwVsZYNq26QS3xfaT3Q==
+
 md5.js@^1.3.4:
   version "1.3.5"
   resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f"
@@ -5041,6 +5183,11 @@ mdn-data@2.0.4:
   resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.4.tgz#699b3c38ac6f1d728091a64650b65d388502fd5b"
   integrity sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==
 
+mdurl@~1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e"
+  integrity sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=
+
 media-typer@0.3.0:
   version "0.3.0"
   resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
@@ -6522,7 +6669,7 @@ pretty-error@^2.0.2:
     renderkid "^2.0.1"
     utila "~0.4"
 
-private@^0.1.6:
+private@^0.1.6, private@~0.1.5:
   version "0.1.8"
   resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff"
   integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==
@@ -6758,6 +6905,16 @@ readdirp@^2.2.1:
     micromatch "^3.1.10"
     readable-stream "^2.0.2"
 
+recast@~0.11.12:
+  version "0.11.23"
+  resolved "https://registry.yarnpkg.com/recast/-/recast-0.11.23.tgz#451fd3004ab1e4df9b4e4b66376b2a21912462d3"
+  integrity sha1-RR/TAEqx5N+bTktmN2sqIZEkYtM=
+  dependencies:
+    ast-types "0.9.6"
+    esprima "~3.1.0"
+    private "~0.1.5"
+    source-map "~0.5.0"
+
 redent@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde"
@@ -6778,6 +6935,11 @@ regenerate@^1.4.0:
   resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11"
   integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==
 
+regenerator-runtime@^0.11.0:
+  version "0.11.1"
+  resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9"
+  integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==
+
 regenerator-runtime@^0.13.2:
   version "0.13.3"
   resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz#7cf6a77d8f5c6f60eb73c5fc1955b2ceb01e6bf5"
@@ -7394,7 +7556,7 @@ source-map@^0.4.2:
   dependencies:
     amdefine ">=0.0.4"
 
-source-map@^0.5.0, source-map@^0.5.6:
+source-map@^0.5.0, source-map@^0.5.6, source-map@~0.5.0:
   version "0.5.7"
   resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
   integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=
@@ -7859,7 +8021,7 @@ through2@^2.0.0:
     readable-stream "~2.3.6"
     xtend "~4.0.1"
 
-through@^2.3.6:
+through@^2.3.6, through@~2.3.6:
   version "2.3.8"
   resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
   integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=
@@ -8013,6 +8175,11 @@ typedarray@^0.0.6:
   resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
   integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
 
+uc.micro@^1.0.1:
+  version "1.0.6"
+  resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac"
+  integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==
+
 uglify-js@3.4.x:
   version "3.4.10"
   resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.10.tgz#9ad9563d8eb3acdfb8d38597d2af1d815f6a755f"
@@ -8083,6 +8250,11 @@ universalify@^0.1.0:
   resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
   integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==
 
+"unorm@>= 1.0.0":
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/unorm/-/unorm-1.6.0.tgz#029b289661fba714f1a9af439eb51d9b16c205af"
+  integrity sha512-b2/KCUlYZUeA7JFUuRJZPUtr4gZvBh7tavtv4fvk4+KV9pfGiR6CQAQAWl49ZpR3ts2dk4FYkP7EIgDJoiOLDA==
+
 unpipe@1.0.0, unpipe@~1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
@@ -8153,6 +8325,13 @@ use@^3.1.0:
   resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f"
   integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==
 
+uslug@^1.0.4:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/uslug/-/uslug-1.0.4.tgz#b9a22f0914e0a86140633dacc302e5f4fa450677"
+  integrity sha1-uaIvCRTgqGFAYz2swwLl9PpFBnc=
+  dependencies:
+    unorm ">= 1.0.0"
+
 util-deprecate@^1.0.1, util-deprecate@~1.0.1:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
@@ -8255,6 +8434,25 @@ vue-loader@^15.7.0:
     vue-hot-reload-api "^2.3.0"
     vue-style-loader "^4.1.0"
 
+vue-markdown@^2.2.4:
+  version "2.2.4"
+  resolved "https://registry.yarnpkg.com/vue-markdown/-/vue-markdown-2.2.4.tgz#db0f774178f3bc91ee18c626d86a3a0d2de22746"
+  integrity sha512-hoTX/W1UIdHZrp/b0vpHSsJXAEfWsafaQLgtE2VX4gY8O/C3L2Gabqu95gyG429rL4ML1SwGv+xsPABX7yfFIQ==
+  dependencies:
+    highlight.js "^9.12.0"
+    markdown-it "^6.0.1"
+    markdown-it-abbr "^1.0.3"
+    markdown-it-deflist "^2.0.1"
+    markdown-it-emoji "^1.1.1"
+    markdown-it-footnote "^2.0.0"
+    markdown-it-ins "^2.0.0"
+    markdown-it-katex "^2.0.3"
+    markdown-it-mark "^2.0.0"
+    markdown-it-sub "^1.0.0"
+    markdown-it-sup "^1.0.0"
+    markdown-it-task-lists "^2.0.1"
+    markdown-it-toc-and-anchor "^4.1.2"
+
 vue-material@^1.0.0-beta-11:
   version "1.0.0-beta-11"
   resolved "https://registry.yarnpkg.com/vue-material/-/vue-material-1.0.0-beta-11.tgz#11baf0cdb22a35d35859c619099d6c3cb3cc2cc3"
@@ -8291,6 +8489,11 @@ vue@^2.6.10:
   resolved "https://registry.yarnpkg.com/vue/-/vue-2.6.10.tgz#a72b1a42a4d82a721ea438d1b6bf55e66195c637"
   integrity sha512-ImThpeNU9HbdZL3utgMCq0oiMzAkt1mcgy3/E6zWC/G6AaQoeuFdsl9nDhTDU3X1R6FK7nsIUuRACVcjI+A2GQ==
 
+vuelidate@^0.7.4:
+  version "0.7.4"
+  resolved "https://registry.yarnpkg.com/vuelidate/-/vuelidate-0.7.4.tgz#5a0e54be09ac0192f1aa3387d74b92e0945bf8aa"
+  integrity sha512-QHZWYOL325Zo+2K7VBNEJTZ496Kd8Z31p85aQJFldKudUUGBmgw4zu4ghl4CyqPwjRCmqZ9lDdx4FSdMnu4fGg==
+
 watchpack@^1.6.0:
   version "1.6.0"
   resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.6.0.tgz#4bc12c2ebe8aa277a71f1d3f14d685c7b446cd00"