diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000000000000000000000000000000000000..b236c5b770f6b9c66e818b73e7497992bfc193a2
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,4 @@
+/node_modules/
+/public/build/
+.DS_Store
+test-results.xml
\ No newline at end of file
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 65b3c840029c89f988b9bd68c635fdb8cc441416..2f96e8bded237585a49354cb5d71a6a55a0789df 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,3 +1,8 @@
+stages:
+  - "test"
+  - "build"
+  - "deploy"
+
 "test:mocha":
   needs: []
   image: "node:18-alpine"
@@ -25,3 +30,48 @@ pages:
       - "public"
   only:
     - "main"
+
+
+build_docker_main:
+  needs: []
+  stage: "build"
+  image:
+    name: "gcr.io/kaniko-project/executor:debug"
+    entrypoint: [ "" ]
+  script:
+    - "mkdir -p /kaniko/.docker"
+    - 'echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > /kaniko/.docker/config.json'
+    - "/kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --destination $CI_REGISTRY_IMAGE:commit-$CI_COMMIT_SHORT_SHA --destination $CI_REGISTRY_IMAGE:latest"
+  rules:
+    - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
+
+build_docker_branches:
+  needs: []
+  stage: "build"
+  image:
+    name: "gcr.io/kaniko-project/executor:debug"
+    entrypoint: [ "" ]
+  script:
+    - "mkdir -p /kaniko/.docker"
+    - 'echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > /kaniko/.docker/config.json'
+    - "/kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --destination $CI_REGISTRY_IMAGE:commit-$CI_COMMIT_SHORT_SHA --destination $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG-latest"
+  rules:
+    - if: '$CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH'
+
+deploy_to_caprover:
+  needs:
+    - "build_docker_main"
+  stage: "deploy"
+  image:
+    name: "caprover/cli-caprover:latest"
+    entrypoint: [ "" ]
+  variables:
+    # We don't need the files, just tell CapRover to use the built docker image:
+    GIT_STRATEGY: none
+  script:
+    - "caprover deploy -h https://captain.$CAPROVER_URL -a $CAPROVER_APP --imageName $CI_REGISTRY_IMAGE:commit-$CI_COMMIT_SHORT_SHA"
+  environment:
+    name: "production"
+    url: "https://$CAPROVER_APP.$CAPROVER_URL/"
+  rules:
+    - if: "$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CAPROVER_URL && $CAPROVER_APP_TOKEN && $CAPROVER_APP"
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..618bf02fae0d98251439cb51da42bfeeb79fe907
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,11 @@
+FROM node:18-alpine AS build
+
+WORKDIR /build
+COPY package.json package-lock.json /build/
+RUN npm install --ignore-scripts
+
+COPY . .
+RUN npm run build
+
+FROM pierrezemb/gostatic AS final
+COPY --from=build /build/public/ /srv/http/
\ No newline at end of file
diff --git a/captain-definition b/captain-definition
new file mode 100644
index 0000000000000000000000000000000000000000..3c53bed15a2a703e696f623c77fbb9acb6b61c0e
--- /dev/null
+++ b/captain-definition
@@ -0,0 +1,4 @@
+{
+  "schemaVersion" :2 ,
+  "dockerfilePath" : "Dockerfile"
+ }
\ No newline at end of file
diff --git a/src/App.svelte b/src/App.svelte
index 2c9fbe1e39b55218889efb493bb75ca4f5f300d8..91210876079a7f87d290b5564a44f0f9c9b759a9 100644
--- a/src/App.svelte
+++ b/src/App.svelte
@@ -56,11 +56,11 @@
       and
       <a href="https://plotly.com/javascript/">Plotly</a>
       <br />
-      <a href="https://oh14.de/datenschutzerklaerung.html"
+      <a href="https://oh14.dev/datenschutz.html"
         >Datenschutzerklärung</a
       >
       -
-      <a href="https://gitlab.fachschaften.org/jfowl/wrums-tools">Source Code</a
+      <a href="https://gitlab.fachschaften.org/oh14-dev/wrums-tools">Source Code</a
       >
     </p>
   </div>