diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 0000000000000000000000000000000000000000..d8b36c9e4231f62cea59976a75b2cd79c575873a
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,209 @@
+## Official docker image, try not to use latest tag.
+image: docker:19.03.1
+
+services:
+  - docker:19.03.1-dind
+
+## Should contain at least these three stages for a basic CI/CD
+stages:
+  - build
+  - review
+  - deploy
+
+variables:
+  ## REMOTE HOST DNS or Private IP of the Deployment VM, please change the example.com with your host
+  DOCKER_BUILDKIT: "1"
+  DOCKER_TLS_CERTDIR: ""
+
+
+k8s-build-production:
+  variables:
+    DOCKER_HOST: tcp://localhost:2375
+
+  stage: build
+  script:
+    ## Login to Gitlab Provided Container Registry for this project.
+    - registry_login
+    ## Install Docker Compose
+    - install_compose
+    - sed_files compose
+    - docker-compose build --pull --compress --force-rm
+    - push_registry
+
+  only:
+    - release
+
+k8s-tag-production:
+  variables:
+    DOCKER_HOST: tcp://localhost:2375
+  stage: build
+  only:
+    - tags
+  script:
+    ## Login to Gitlab Provided Container Registry for this project.
+    - registry_login
+    ## Install Docker Compose
+    - install_compose
+    - sed_files compose
+    - docker-compose pull
+    - push_registry
+
+
+deploy_review:
+  image:
+    name: lachlanevenson/k8s-kubectl:latest
+    entrypoint: ["/bin/sh", "-c"]
+  stage: review
+  only:
+    - branches
+  except:
+    - tags
+  environment:
+    name: review/$CI_BUILD_REF_NAME
+    url: https://$CI_ENVIRONMENT_SLUG.104.154.109.250.nip.io
+    on_stop: stop_review
+  script:
+    - kubectl version
+    - sed_files deployment
+    - cat kube-deployment.yml
+    - kubectl apply -f kube-deployment.yml
+    # - |
+    #   if kubectl apply -f kube-deployment.yml | grep -q unchanged
+    #   then
+    #       echo "=> Patching deployment to force image update."
+    #       kubectl patch -f kube-deployment.yml -p "{\"spec\":{\"template\":{\"metadata\":{\"annotations\":{\"ci-last-updated\":\"$(date +'%s')\"}}}}}"
+    #   else
+    #       echo "=> Deployment apply has changed the object, no need to force image update."
+    #   fi
+    # - kubectl rollout status -f kube-deployment.yml
+    - kubectl get deploy,svc,ing,pod -l app="$(echo ${CI_PROJECT_NAME} | tr "." "-")",ref="${CI_ENVIRONMENT_SLUG}"
+
+stop_review:
+  image:
+    name: lachlanevenson/k8s-kubectl:latest
+    entrypoint: ["/bin/sh", "-c"]
+  stage: review
+  variables:
+    GIT_STRATEGY: none
+  when: manual
+  only:
+    - release
+  except:
+    - tags
+  environment:
+    name: review/$CI_BUILD_REF_NAME
+    action: stop
+  script:
+    - kubectl version
+    - kubectl delete ing -l ref=${CI_ENVIRONMENT_SLUG}
+    - kubectl delete all -l ref=${CI_ENVIRONMENT_SLUG}
+
+deploy_live:
+  image:
+    name: lachlanevenson/k8s-kubectl:latest
+    entrypoint: ["/bin/sh", "-c"]
+  stage: deploy
+  environment:
+    name: live
+    url: $AUTO_DEVOPS_DOMAIN
+  only:
+    - tags
+  when: manual
+  script:
+    - kubectl version
+    - sed_files deployment
+    - kubectl apply -f kube-deployment.yml
+    # - kubectl rollout status -f kube-deployment.yml
+    - kubectl get deploy,svc,ing,pod -l app="$(echo ${CI_PROJECT_NAME} | tr "." "-")",ref="${CI_ENVIRONMENT_SLUG}"
+
+.helper_functions: &helper_functions_template |
+  function registry_login() {
+    if [[ -n "$CI_REGISTRY_USER" ]]
+    then
+      echo "Logging to GitLab Container Registry with CI credentials..."
+      docker login -u gitlab-ci-token -p "$CI_BUILD_TOKEN" "$CI_REGISTRY"
+      echo ""
+    fi
+  }
+
+  function install_compose() {
+    # if [-n "which apt-get"]]
+    # then
+      echo "Installing Docker Compose on Linux"
+      which docker-compose || apk add --no-cache docker-compose
+    # else
+    #   echo "Installing Docker Compose on Debian"
+    #   which docker-compose || apt-get install docker-compose -y
+    # fi
+  }
+
+  function sed_files() {
+    file_type=${1:-compose}
+
+    echo "File Type is $file_type"
+
+    if [[ "$file_type" == "deployment" ]]
+    then
+      echo "Applying SED on Deployment Yamls"
+      sed -i "s~__CI_REGISTRY_IMAGE__~${CI_REGISTRY_IMAGE}~" kube-deployment.yml
+      sed -i "s/__CI_ENVIRONMENT_SLUG__/${CI_ENVIRONMENT_SLUG}/" kube-deployment.yml
+      sed -i "s/__VERSION__/${CI_COMMIT_REF_NAME}/" kube-deployment.yml
+      sed -i "s/__CI_PROJECT_NAME__/${CI_PROJECT_NAME}/" kube-deployment.yml
+      sed -i "s/__CI_PROJECT_PATH_SLUG__/${CI_PROJECT_PATH_SLUG}/" kube-deployment.yml
+    else
+      echo "Applying SED on compose Yamls"
+      sed -i "s~__CI_REGISTRY_IMAGE__~${CI_REGISTRY_IMAGE}~" docker-compose.yml
+    fi
+  }
+
+  function push_registry() {
+
+    ## Tag All microservices one by one. Note that docker-compose will build with project_service pattern
+    echo "Tagging Docker Images"
+    docker tag "${CI_REGISTRY_IMAGE}/backend:latest" "${CI_REGISTRY_IMAGE}/backend:${CI_COMMIT_REF_NAME}"
+    docker tag "${CI_REGISTRY_IMAGE}/frontend:latest" "${CI_REGISTRY_IMAGE}/frontend:${CI_COMMIT_REF_NAME}"
+
+    ## Check if there is a Commit Tag then release a latest release.
+    if [[ -n $CI_COMMIT_TAG]]
+    then
+      echo "Pushing Docker Latest Images to Container Registry"
+      docker push "${CI_REGISTRY_IMAGE}/backend:latest"
+      docker push "${CI_REGISTRY_IMAGE}/frontend:latest"
+    fi
+
+    ## Release a versioned image everytime.
+    echo "Pushing Docker $CI_COMMIT_REF_NAME Images to Container Registry"
+    docker push "$CI_REGISTRY_IMAGE"/backend:$CI_COMMIT_REF_NAME
+    docker push "$CI_REGISTRY_IMAGE"/frontend:$CI_COMMIT_REF_NAME
+  }
+
+  function code_quality() {
+    docker run --env SOURCE_CODE="$PWD" \
+               --volume "$PWD":/code \
+               --volume /var/run/docker.sock:/var/run/docker.sock \
+               "registry.gitlab.com/gitlab-org/security-products/codequality:$SP_VERSION" /code
+  }
+
+  function ensure_namespace() {
+    kubectl describe namespace "$KUBE_NAMESPACE" || kubectl create namespace "$KUBE_NAMESPACE"
+  }
+
+  function check_kube_domain() {
+    if [ -z ${AUTO_DEVOPS_DOMAIN+x} ]
+    then
+      echo "In order to deploy or use Review Apps, AUTO_DEVOPS_DOMAIN variable must be set"
+      echo "You can do it in Auto DevOps project settings or defining a variable at group or project level"
+      echo "You can also manually add it in .gitlab-ci.yml"
+      false
+    else
+      true
+    fi
+  }
+
+  function persist_environment_url() {
+      echo $CI_ENVIRONMENT_URL > environment_url.txt
+  }
+
+
+before_script:
+  - *helper_functions_template
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000000000000000000000000000000000000..b76c901746aa0b5792bb29b785ea81a37ac0fd78
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,33 @@
+version: '3'
+services:
+  backend:
+    build:
+      context: ./backend
+      dockerfile: backend/Dockerfile
+    image: __CI_REGISTRY_IMAGE__/backend:latest
+    ports:
+      - "3080:3080"
+    container_name: backend
+    volumes:
+      - ./backend:/usr/src/app/backend
+      - /usr/src/app/backend/node_modules
+    networks:
+      - back-tier
+
+  frontend:
+    build:
+      context: ./frontend
+      dockerfile: frontend/Dockerfile
+    image: __CI_REGISTRY_IMAGE__/frontend:latest
+    ports:
+      - "8080:8080"
+    container_name: frontend
+    volumes:
+      - ./frontend:/usr/src/app/frontend
+      - /usr/src/app/frontend/node_modules
+    networks:
+      - front-tier
+
+networks:
+  front-tier:
+  back-tier:
diff --git a/kube-deployment.yml b/kube-deployment.yml
new file mode 100644
index 0000000000000000000000000000000000000000..fd1eaeaa7f98dd1c4e9159ca617faf36167a7b5e
--- /dev/null
+++ b/kube-deployment.yml
@@ -0,0 +1,146 @@
+# backend
+---
+apiVersion: v1
+kind: Service
+metadata:
+  name: backend
+  labels:
+    app: backend-__CI_PROJECT_NAME__
+    ref: __CI_ENVIRONMENT_SLUG__
+spec:
+  type: NodePort
+  ports:
+    - port: 3080
+      targetPort: 3080
+      name: backend
+  selector:
+    app: backend-__CI_PROJECT_NAME__
+---
+# Default HTTP BACKEND SERVICE
+apiVersion: v1
+kind: Service
+metadata:
+  name: default-http-backend
+  labels:
+    app: default-http-__CI_PROJECT_NAME__
+    ref: __CI_ENVIRONMENT_SLUG__
+spec:
+  type: NodePort
+  ports:
+    - port: 3080
+      targetPort: 3080
+      name: backend
+  selector:
+    app: backend-__CI_PROJECT_NAME__
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: backend
+  labels:
+    app: backend-__CI_PROJECT_NAME__
+    ref: __CI_ENVIRONMENT_SLUG__
+spec:
+  replicas: 2
+  selector:
+    matchLabels:
+      app: backend-__CI_PROJECT_NAME__
+  template:
+    metadata:
+      labels:
+        app: backend-__CI_PROJECT_NAME__
+        ref: __CI_ENVIRONMENT_SLUG__
+      annotations:
+        app.gitlab.com/app: __CI_PROJECT_PATH_SLUG__
+        app.gitlab.com/env: __CI_ENVIRONMENT_SLUG__
+    spec:
+      containers:
+        - name: backend
+          image: __CI_REGISTRY_IMAGE__/backend:__VERSION__
+          ports:
+            - containerPort: 3080
+              name: backend
+
+# frontend
+---
+apiVersion: v1
+kind: Service
+metadata:
+  name: frontend
+  labels:
+    app: frontend-__CI_PROJECT_NAME__
+    ref: __CI_ENVIRONMENT_SLUG__
+spec:
+  type: NodePort
+  ports:
+    - port: 8080
+      targetPort: 8080
+      name: frontend
+  selector:
+    app: frontend-__CI_PROJECT_NAME__
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: frontend
+  labels:
+    app: frontend-__CI_PROJECT_NAME__
+    ref: __CI_ENVIRONMENT_SLUG__
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      app: frontend-__CI_PROJECT_NAME__
+  template:
+    metadata:
+      labels:
+        app: frontend-__CI_PROJECT_NAME__
+        ref: __CI_ENVIRONMENT_SLUG__
+      annotations:
+        app.gitlab.com/app: __CI_PROJECT_PATH_SLUG__
+        app.gitlab.com/env: __CI_ENVIRONMENT_SLUG__
+    spec:
+      containers:
+        - name: frontend
+          image: __CI_REGISTRY_IMAGE__/frontend:__VERSION__
+          ports:
+            - containerPort: 8080
+              name: frontend
+
+---
+# Ingress Resource
+apiVersion: networking.k8s.io/v1beta1
+kind: Ingress
+metadata:
+  name: app-ingress
+  annotations:
+    kubernetes.io/tls-acme: "true"
+    kubernetes.io/ingress.class: "nginx"
+  labels:
+    app: ingress-__CI_PROJECT_NAME__
+    ref: __CI_ENVIRONMENT_SLUG__
+
+spec:
+  tls:
+    - hosts:
+        - __CI_ENVIRONMENT_SLUG__.frontend.__KUBE_INGRESS_BASE_DOMAIN__
+        - __CI_ENVIRONMENT_SLUG__.backend.__KUBE_INGRESS_BASE_DOMAIN__
+      # the secret used here is an unsigned wildcard cert for demo purposes
+      # use your own or comment this out
+      # secretName: tls-some-wildcard-demo
+  rules:
+    - host: __CI_ENVIRONMENT_SLUG__.frontend.__KUBE_INGRESS_BASE_DOMAIN__
+      http:
+        paths:
+          - path: /
+            backend:
+              serviceName: frontend
+              servicePort: 8080
+    - host: __CI_ENVIRONMENT_SLUG__.backend.__KUBE_INGRESS_BASE_DOMAIN__
+      http:
+        paths:
+          - path: /
+            backend:
+              serviceName: backend
+              servicePort: 3080
+---