diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000000000000000000000000000000000000..8a0cb9d2697c1f75be1bbedf2a83d99390d17050
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,45 @@
+# docker
+Dockerfile*
+docker-compose*
+
+# git
+.git
+.gitignore
+
+# npm & yarn
+node_modules
+npm-debug.log
+package-lock.json
+yarn-error.log
+
+# misc
+.devcontainer
+.DS_Store
+.vscode
+app.pid
+
+# environment files
+.env*
+*.env
+
+# app
+editors/demo/build/
+coverage/
+cypress/
+logs/
+stories/
+tmp/
+
+# Include README.md and LICENSE.md, exlcude the rest
+*.md
+!README.md
+!LICENSE.md
+
+# development config files
+# .eslintrc.js
+.commitlintrc.js
+.cz-config.js
+.gitlab-ci.yml
+.linstagedrc.js
+# .prettierrc.js
+# .stylelintrc.js
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 0000000000000000000000000000000000000000..7a3ffcf39653a4bfd7c436eda55e8025811e050d
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,26 @@
+variables:
+  IMAGE_NAME_DEPLOY: wax-demo
+
+include:
+  - project: 'cokoapps/ci'
+    ref: main
+    file: 'ci-templates.yml'
+
+stages:
+  - Build demo
+  - Deploy demo
+
+build demo image:
+  extends: .build production
+  stage: Build demo
+  variables:
+    IMAGE_NAME: $IMAGE_NAME_DEPLOY
+    BUILD_PATH: ./
+  only:
+    - master
+
+deploy demo:
+  extends: .deploy
+  stage: Deploy demo
+  only:
+    - master
diff --git a/Dockerfile-production b/Dockerfile-production
new file mode 100644
index 0000000000000000000000000000000000000000..4331b7e69d4d466373750b6a131c8c1f3f61688e
--- /dev/null
+++ b/Dockerfile-production
@@ -0,0 +1,41 @@
+########
+# BUILD
+
+FROM node:16-bullseye-slim
+
+RUN apt-get update && \
+    apt-get upgrade -y
+
+WORKDIR /home/wax
+
+COPY package.json .
+COPY editors/demo/package.json editors/demo/
+COPY wax-prosemirror-core/package.json wax-prosemirror-core/
+COPY wax-prosemirror-services/package.json wax-prosemirror-services/
+COPY wax-questions-service/package.json wax-questions-service/
+COPY wax-table-service/package.json wax-table-service/
+COPY yarn.lock .
+
+RUN yarn install --frozen-lockfile
+
+COPY . .
+
+RUN cd editors/demo && yarn react-app-rewired build
+
+######
+# RUN
+
+FROM node:16-bullseye
+
+RUN apt-get update && \
+    apt-get upgrade -y
+
+RUN npm install --global serve
+
+WORKDIR /home/wax
+
+USER node
+
+COPY --from=0 /home/wax/editors/demo/build ./_build
+
+CMD ["npx", "serve", "--single", "./_build"]
diff --git a/docker-compose.deploy.yml b/docker-compose.deploy.yml
new file mode 100644
index 0000000000000000000000000000000000000000..285c82a3d452c57fc0527d2c9edd2f642ad8732a
--- /dev/null
+++ b/docker-compose.deploy.yml
@@ -0,0 +1,7 @@
+version: '3'
+
+services:
+  client:
+    image: cokoapps/wax-demo
+    ports:
+      - ${PORT}:3000
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000000000000000000000000000000000000..99faa83432bba59fdbb973dca16fe7e8e81905e8
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,7 @@
+version: '3'
+
+services:
+  wax:
+    build:
+      context: .
+      dockerfile: Dockerfile-production
diff --git a/editors/demo/package-lock.json b/editors/demo/package-lock.json
deleted file mode 100644
index 1f1a2e4b0431228f40684ffbbeda032ae1bc271f..0000000000000000000000000000000000000000
--- a/editors/demo/package-lock.json
+++ /dev/null
@@ -1,86 +0,0 @@
-{
-  "name": "editoria",
-  "version": "0.8.20",
-  "lockfileVersion": 1,
-  "requires": true,
-  "dependencies": {
-    "cross-spawn": {
-      "version": "6.0.5",
-      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
-      "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
-      "dev": true,
-      "requires": {
-        "nice-try": "^1.0.4",
-        "path-key": "^2.0.1",
-        "semver": "^5.5.0",
-        "shebang-command": "^1.2.0",
-        "which": "^1.2.9"
-      }
-    },
-    "dotenv": {
-      "version": "6.2.0",
-      "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-6.2.0.tgz",
-      "integrity": "sha512-HygQCKUBSFl8wKQZBSemMywRWcEDNidvNbjGVyZu3nbZ8qq9ubiPoGLMdRDpfSrpkkm9BXYFkpKxxFX38o/76w==",
-      "dev": true
-    },
-    "isexe": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
-      "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
-      "dev": true
-    },
-    "nice-try": {
-      "version": "1.0.5",
-      "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
-      "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
-      "dev": true
-    },
-    "path-key": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
-      "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=",
-      "dev": true
-    },
-    "react-app-rewired": {
-      "version": "2.1.3",
-      "resolved": "https://registry.npmjs.org/react-app-rewired/-/react-app-rewired-2.1.3.tgz",
-      "integrity": "sha512-NXC2EsQrnEMV7xD70rHcBq0B4PSEzjY/K2m/e+GRgit2jZO/uZApnpCZSKvIX2leLRN69Sqf2id0VXZ1F62CDw==",
-      "dev": true,
-      "requires": {
-        "cross-spawn": "^6.0.5",
-        "dotenv": "^6.2.0",
-        "semver": "^5.6.0"
-      }
-    },
-    "semver": {
-      "version": "5.7.0",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz",
-      "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==",
-      "dev": true
-    },
-    "shebang-command": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
-      "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
-      "dev": true,
-      "requires": {
-        "shebang-regex": "^1.0.0"
-      }
-    },
-    "shebang-regex": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
-      "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
-      "dev": true
-    },
-    "which": {
-      "version": "1.3.1",
-      "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
-      "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
-      "dev": true,
-      "requires": {
-        "isexe": "^2.0.0"
-      }
-    }
-  }
-}