diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index e4688ce940240259bb27bbfe53d926a0b1b62cf4..64e443696ac2a9a1d4ac35419e1af9fd7cf180e8 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,6 +1,3 @@
-variables:
-  docker_registry_user: "robot$$gitlab"
-
 stages:
   - build
 
@@ -14,3 +11,15 @@ build_image:
     - tags
   tags:
     - shell-runner
+
+build_latest_dev_image:
+  stage: build
+  script:
+    - docker build -f base/Dockerfile -t docker-registry.ebrains.eu/clb-jupyter-image/ebrains:dev-$CI_COMMIT_SHORT_SHA .
+    - docker login -u $docker_registry_user -p $docker_registry_prod_token docker-registry.ebrains.eu
+    - docker push docker-registry.ebrains.eu/clb-jupyter-image/ebrains:dev-$CI_COMMIT_SHORT_SHA
+  rules:
+    - if: $CI_COMMIT_BRANCH =~ /dev/
+      when: manual
+  tags:
+    - shell-runner
diff --git a/base/Dockerfile b/base/Dockerfile
index a30e1e4f7996c529827d304d709b6363fe3e20f7..c0c71814420300fd5ce9d594e97b5fd6c67e8668 100644
--- a/base/Dockerfile
+++ b/base/Dockerfile
@@ -1,11 +1,8 @@
-FROM docker-registry.ebrains.eu/clb-jupyter-image/ubuntu:focal
+# https://jupyter-docker-stacks.readthedocs.io/en/latest/#using-old-images
+FROM jupyter/minimal-notebook:a374cab4fcb6
 
 LABEL maintainer="Collaboratory Platform <platform@humanbrainproject.eu>"
 
-ARG NB_USER="jovyan"
-ARG NB_UID=1000
-ARG NB_GID=100
-
 ENV GIT_COMMITTER_NAME=platform@humanbrainproject.eu \
     GIT_COMMITTER_EMAIL=platform@humanbrainproject.eu \
     USER="${NB_USER}" \
@@ -24,44 +21,22 @@ RUN ln -sf /usr/share/zoneinfo/Europe/Zurich /etc/localtime
 ENV DEBIAN_FRONTEND noninteractive
 RUN apt-get update --yes && \
     apt-get install --yes \
-    ca-certificates \
     cmake \
     csh \
     curl \
     cython \
     gcc \
     gettext \
-    git \
-    libnss-wrapper \
     llvm \
     lsof \
     mpich \
-    pandoc \
-    python-dev \
-    python3-venv \
-    python3-pip \
     r-base \
     swig \
-    unzip \
     vim  && \
     apt-get clean && rm -rf /var/lib/apt/lists/*
 
-# install nodejs
-RUN curl -fsSL https://deb.nodesource.com/setup_17.x | bash
-RUN apt-get install -y nodejs
-
-# install min texlive (necessary for nb exports)
-RUN apt-get update --yes && \
-    apt-get install --yes --no-install-recommends \
-    wget \
-    texlive-xetex \
-    texlive-fonts-recommended \
-    texlive-plain-generic && \
-    apt-get clean && rm -rf /var/lib/apt/lists/*
-
 # jupyter install in /opt/app-root/ for legacy reasons (previously based on centos base image)
 RUN mkdir -p /opt/app-root/etc /opt/app-root/clb/ /opt/app-root/src
-COPY base/jupyter_notebook_config.py /opt/app-root/etc/
 
 # folders for drive integration
 RUN mkdir -p /mnt/user/
@@ -70,21 +45,20 @@ RUN ln -s /mnt/user/shared /opt/app-root/src/shared
 
 ENV HOME=/opt/app-root/src/
 
+# temporarily downgrade pip to avoid failing build because of dependency conflicts (TODO: fix)
+RUN pip install pip==20.0.2
+
 # install pip packages
 COPY base/requirements.txt /tmp
 RUN pip install --no-cache-dir -r /tmp/requirements.txt
 
-# fix missing template issue in nbgitpuller: https://github.com/jupyterhub/nbgitpuller/issues/235
-# remove this once it has been fixed in project
-RUN ln -s /usr/local/lib/python3.8/dist-packages/nbgitpuller/templates/status.html /usr/local/lib/python3.8/dist-packages/notebook/templates/
-
 # disable ipcluster extension
 RUN jupyter labextension disable ipcluster \
                               ipyparallel-labextension
 
-# install additional labextensions
+# install additional labextensions (TODO: install with pip, if possible)
 RUN jupyter labextension install --no-build \
-                             clb-jupyter-ext-query-params@3.2.0 \
+                             clb-jupyter-ext-query-params-dev@3.2.0 \
                              clb-lab-extension@0.9.2 \
                              ipycanvas@0.12.0
 # ipycanvas@0.12.0: Python part installed via spack (py-ipycanvas@0.12.0)
@@ -104,9 +78,8 @@ RUN R --slave -e "IRkernel::installspec(name = 'ir363', displayname = 'R 3.6.3')
 # disable core dumps
 RUN echo "* - core 0" >> /etc/security/limits.conf
 
-# fix permissions so NB_USER has permissions to run notebooks and install packages
-COPY base/fix-permissions /usr/local/bin/fix-permissions
-RUN chmod +x /usr/local/bin/fix-permissions
+# allow the script to fail (because of symlinks) without failing the build (TODO: fix)
+RUN sed -i 's/set -e/set +e/' $(which fix-permissions)
 
 # copy user setup file
 COPY base/user_setup.sh /opt/app-root/etc/
@@ -114,23 +87,12 @@ RUN chmod +x /opt/app-root/etc/user_setup.sh
 
 RUN fix-permissions /opt/app-root/ && \
     fix-permissions /tmp/cache/ && \
-    fix-permissions /usr/local/share/jupyter/ && \
-    fix-permissions /usr/local/etc/jupyter && \
-    fix-permissions /usr/local/lib/R/site-library && \
-    fix-permissions /usr/etc/jupyter/
-
-# to support OpenShift's arbitrary UIDs
-# more info: https://docs.openshift.com/enterprise/3.1/creating_images/guidelines.html
-COPY base/passwd.template /tmp/passwd.template
-COPY base/group.template /tmp/group.template
-COPY base/start-notebook.sh /opt/app-root/etc/
+    fix-permissions /opt/conda/share/jupyter/ && \
+    fix-permissions /opt/conda/etc/jupyter && \
+    fix-permissions /usr/local/lib/R/site-library
+
 COPY base/.spynnaker.cfg /opt/app-root/src/
-RUN chmod +x /opt/app-root/etc/start-notebook.sh
 
 WORKDIR /opt/app-root/src/
 
-EXPOSE 8080
-
 USER ${NB_UID}
-
-CMD /opt/app-root/etc/start-notebook.sh
diff --git a/base/fix-permissions b/base/fix-permissions
deleted file mode 100644
index 45354c0dccbadfef143fc32333a8b240430d3d89..0000000000000000000000000000000000000000
--- a/base/fix-permissions
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/bin/sh
-# source: https://github.com/sclorg/s2i-base-container/blob/master/core/root/usr/bin/fix-permissions
-
-# Allow this script to fail without failing a build
-set +e
-
-SYMLINK_OPT=${2:--L}
-
-# Fix permissions on the given directory or file to allow group read/write of
-# regular files and execute of directories.
-
-[ $(id -u) -ne 0 ] && CHECK_OWNER=" -uid $(id -u)"
-
-# If argument does not exist, script will still exit with 0,
-# but at least we'll see something went wrong in the log
-if ! [ -e "$1" ] ; then
-  echo "ERROR: File or directory $1 does not exist." >&2
-  # We still want to end successfully
-  exit 0
-fi
-
-find $SYMLINK_OPT "$1" ${CHECK_OWNER} \! -gid 0 -exec chgrp 0 {} +
-find $SYMLINK_OPT "$1" ${CHECK_OWNER} \! -perm -g+rw -exec chmod g+rw {} +
-find $SYMLINK_OPT "$1" ${CHECK_OWNER} -perm /u+x -a \! -perm /g+x -exec chmod g+x {} +
-find $SYMLINK_OPT "$1" ${CHECK_OWNER} -type d \! -perm /g+x -exec chmod g+x {} +
-
-# Always end successfully
-exit 0
\ No newline at end of file
diff --git a/base/group.template b/base/group.template
deleted file mode 100644
index a957d0695246d100aae8a5ed23b5922d2688f361..0000000000000000000000000000000000000000
--- a/base/group.template
+++ /dev/null
@@ -1,2 +0,0 @@
-nb_group:x:${GROUP_ID}:
-nb_group_user:x:${USER_ID}:
\ No newline at end of file
diff --git a/base/jupyter_notebook_config.py b/base/jupyter_notebook_config.py
deleted file mode 100644
index 6b9fc72094b87c9749d64cced15572d7fb6a21ac..0000000000000000000000000000000000000000
--- a/base/jupyter_notebook_config.py
+++ /dev/null
@@ -1,26 +0,0 @@
-import os
-
-port = int(os.environ.get('JUPYTER_NOTEBOOK_PORT', '8080'))
-
-c.NotebookApp.ip = '0.0.0.0'
-c.NotebookApp.port = port
-c.NotebookApp.open_browser = False
-c.NotebookApp.quit_button = False
-
-c.WebPDFExporter.enabled = False
-
-if os.environ.get('JUPYTERHUB_SERVICE_PREFIX'):
-    c.NotebookApp.base_url = os.environ.get('JUPYTERHUB_SERVICE_PREFIX')
-
-password = os.environ.get('JUPYTER_NOTEBOOK_PASSWORD')
-if password:
-    import notebook.auth
-    c.NotebookApp.password = notebook.auth.passwd(password)
-    del password
-    del os.environ['JUPYTER_NOTEBOOK_PASSWORD']
-
-image_config_file = '/opt/app-root/src/.jupyter/jupyter_notebook_config.py'
-
-if os.path.exists(image_config_file):
-    with open(image_config_file) as fp:
-        exec(compile(fp.read(), image_config_file, 'exec'), globals())
diff --git a/base/passwd.template b/base/passwd.template
deleted file mode 100644
index bb42cf7afc363193bab1ddbab51a1d8b76341105..0000000000000000000000000000000000000000
--- a/base/passwd.template
+++ /dev/null
@@ -1,14 +0,0 @@
-root:x:0:0:root:/root:/bin/bash
-bin:x:1:1:bin:/bin:/sbin/nologin
-daemon:x:2:2:daemon:/sbin:/sbin/nologin
-adm:x:3:4:adm:/var/adm:/sbin/nologin
-lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
-sync:x:5:0:sync:/sbin:/bin/sync
-shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
-halt:x:7:0:halt:/sbin:/sbin/halt
-mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
-operator:x:11:0:operator:/root:/sbin/nologin
-games:x:12:100:games:/usr/games:/sbin/nologin
-ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
-nobody:x:99:99:Nobody:/:/sbin/nologin
-${USER}:x:${USER_ID}:${GROUP_ID}:${USER_DESCRIPTION}:${HOME}:/bin/bash
\ No newline at end of file
diff --git a/base/requirements.txt b/base/requirements.txt
index cb25f19118c1dde5c863f0cfaa7020317aca841a..9929e0c05e0521fd9767f225f25d0013859d70cc 100644
--- a/base/requirements.txt
+++ b/base/requirements.txt
@@ -1,9 +1,6 @@
-beautifulsoup4==4.10.0
 bluepyopt==1.11.5
 bokeh==2.4.2
 Cython==0.29.26
-cffi==1.14.5
-cryptography==36.0.1
 ebrains-drive==0.5.0
 h5py==3.6.0
 ipympl==0.8.5
@@ -11,10 +8,7 @@ ipywidgets==7.6.5
 jupyterlab-widgets==1.0.2
 jupyterlab-topbar==0.6.1
 jupyterlab-system-monitor==0.8.0
-jupyterhub==1.5.0
-jupyterlab==3.2.8
 jupyterlab-git==0.34.1
-jupyter-server==1.13.5
 lazyarray==0.5.1
 lxml==4.7.1
 matplotlib==3.5.3
@@ -31,9 +25,7 @@ numpy==1.23.5
 pandas==1.3.5
 patsy==0.5.2
 plotly==5.5.0
-Pygments==2.11.2
 python-swiftclient==3.13.0
-PyJWT==2.3.0
 pyOpenSSL==22.0.0 # TODO: Issue with 22.1 https://github.com/pyca/pyopenssl/issues/1154
 pyunicore==0.15.0
 requests-oauthlib==1.3.0
diff --git a/base/start-notebook.sh b/base/start-notebook.sh
deleted file mode 100644
index 0acc0fb45174f4bd899b1cd6357bf8f530cff31c..0000000000000000000000000000000000000000
--- a/base/start-notebook.sh
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/bash
-set -e
-# to support OpenShift's arbitrary UIDs
-# more info: https://docs.openshift.com/enterprise/3.1/creating_images/guidelines.html
-export USER_ID=$(id -u)
-export GROUP_ID=$(id -g)
-export USER_DESCRIPTION="Notebook User"
-envsubst < /tmp/passwd.template > /tmp/passwd
-envsubst < /tmp/group.template > /tmp/group
-export LD_PRELOAD=libnss_wrapper.so
-export NSS_WRAPPER_PASSWD=/tmp/passwd
-export NSS_WRAPPER_GROUP=/tmp/group
-# Disable core dumps
-ulimit -c 0
-exec jupyter labhub --NotebookApp.default_url=/lab --config=/opt/app-root/etc/jupyter_notebook_config.py $@