diff --git a/.github/workflows/code/create-checklist-comment.js b/.github/workflows/code/create-checklist-comment.js
index f59b6f7516501d28f41416550f1d2f110861832f..47a4cdd8b28ede90b165a543dcd105734c0d1dd1 100644
--- a/.github/workflows/code/create-checklist-comment.js
+++ b/.github/workflows/code/create-checklist-comment.js
@@ -1,5 +1,5 @@
 module.exports = async ({github, context}) => {
-  const pathToChecklist = './e2e/checklist.md'
+  const pathToChecklist = './checklist.md'
   const fs = require('fs')
   const { promisify } = require('util')
   const asyncReadFile = promisify(fs.readFile)
diff --git a/.github/workflows/docker_img.yml b/.github/workflows/docker_img.yml
index 54c2713dfa3ed669c446a6ae1298040a4e82400b..acd0d525a9393f0580ba06599ace4992341c3d69 100644
--- a/.github/workflows/docker_img.yml
+++ b/.github/workflows/docker_img.yml
@@ -65,9 +65,18 @@ jobs:
     - id: 'build-docker-image'
       name: 'Build docker image'
       run: |
+        GIT_DIGEST=${{ github.sha }}
+        echo "Git digest: $GIT_DIGEST"
+
+        # 62 char limit in label
+        GIT_DIGEST=$(echo $GIT_DIGEST | grep -oP '^.{6}')
+        echo "Using first 6 chars of hash: $GIT_DIGEST"
+        echo "GIT_DIGEST=$GIT_DIGEST" >> $GITHUB_OUTPUT
+
         DOCKER_BUILT_TAG=${{ env.DOCKER_REGISTRY }}siibra-explorer:$BRANCH_NAME
         echo "Building $DOCKER_BUILT_TAG"
         docker build \
+          --build-arg BUILD_HASH=$GIT_DIGEST \
           --build-arg MATOMO_URL=$MATOMO_URL \
           --build-arg MATOMO_ID=$MATOMO_ID \
           --build-arg SIIBRA_API_ENDPOINTS=$SIIBRA_API_ENDPOINTS \
@@ -79,15 +88,6 @@ jobs:
 
         inspect_str=$(docker image inspect --format='json' $DOCKER_BUILT_TAG)
         echo "Inspected tag: $inspect_str"
-        
-        GIT_DIGEST=${{ github.sha }}
-        echo "Git digest: $GIT_DIGEST"
-
-        # 62 char limit in label
-        GIT_DIGEST=$(echo $GIT_DIGEST | grep -oP '^.{6}')
-        echo "Using first 6 chars of hash: $GIT_DIGEST"
-
-        echo "GIT_DIGEST=$GIT_DIGEST" >> $GITHUB_OUTPUT
 
     - name: 'Push to docker registry'
       run: |
@@ -155,6 +155,75 @@ jobs:
     secrets:
       KUBECONFIG: ${{ secrets.KUBECONFIG }}
 
+  cypress-staging:
+    needs:
+    - trigger-deploy-rc-rancher
+    runs-on: ${{ matrix.os }}
+    strategy:
+      fail-fast: false
+      matrix:
+        os: 
+        - ubuntu-latest
+        # - windows-latest
+        - macos-latest
+        viewer:
+        - ng
+        - fsa
+        browser:
+        - chrome
+        - webkit
+        include:
+        - viewer: ng
+          url: https://atlases.ebrains.eu/viewer-staging/go/human
+        - viewer: fsa
+          url: https://atlases.ebrains.eu/viewer-staging/go/fsaverage
+        exclude:
+        - os: ubuntu-latest
+          browser: webkit
+        # - os: windows-latest
+        #   browser: webkit
+
+    steps:
+    - uses: actions/checkout@v4
+    - uses: actions/setup-node@v4
+      with:
+        node-version: 20
+    - name: Set variables
+      run: |
+        GIT_DIGEST=${{ github.sha }}
+        GIT_DIGEST=$(echo $GIT_DIGEST | head -c 6)
+
+        SCREENSHOT_URL=${{ matrix.url }}
+        SCREENSHOT_PATH=screenshot_"$GIT_DIGEST"_${{ matrix.viewer }}_${{ matrix.os }}_${{ matrix.browser }}
+
+        echo "SCREENSHOT_URL: $SCREENSHOT_URL"
+        echo "SCREENSHOT_PATH: $SCREENSHOT_PATH"
+
+        echo "SCREENSHOT_URL=$SCREENSHOT_URL" >> $GITHUB_ENV
+        echo "SCREENSHOT_PATH=$SCREENSHOT_PATH" >> $GITHUB_ENV
+
+    - name: Install dependency
+      run: npm install cypress
+
+    - name: Install optional dependency
+      if: ${{ matrix.browser == 'webkit' }}
+      run: |
+        npm install --save-dev playwright-webkit
+        echo "USE_SAFARI=1" >> $GITHUB_ENV
+
+    - name: Run Cypress
+      uses: cypress-io/github-action@v6
+      with:
+        spec: cypress/e2e/screenshot.cy.js
+        browser: ${{ matrix.browser }}
+        
+    - uses: actions/upload-artifact@v4
+      with:
+        name: ${{ env.SCREENSHOT_PATH }}
+        path: cypress/screenshots/screenshot.cy.js/*.png
+        retention-days: 5
+
+
   trigger-deploy-expmt-rancher:
     if: ${{ needs.setting-vars.outputs.BRANCH_NAME == 'staging' && success() }}
     needs:
diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml
deleted file mode 100644
index 5ddc69dde8c3b983df3af45941d4894bf7be0bc9..0000000000000000000000000000000000000000
--- a/.github/workflows/e2e.yml
+++ /dev/null
@@ -1,116 +0,0 @@
-name: "[e2e] prod-specs"
-
-on:
-  workflow_dispatch:
-    inputs:
-      url:
-        required: true
-        default: https://interactive-viewer-next.apps-dev.hbp.eu/
-      sha:
-        required: true
-        default: ''
-
-jobs:
-  update-e2e-status:
-    runs-on: ubuntu-latest
-    env:
-      URL_ROOT: https://api.github.com/repos/HumanBrainProject/interactive-viewer
-      SHA: ${{ github.event.inputs.sha }}
-    steps:
-      - name: update commit status
-        run: |
-          curl -v \
-            -X POST \
-            -H "Authorization: Bearer ${{ github.token }}" \
-            -H 'accept: application/vnd.github.v3+json' \
-            ${URL_ROOT}/statuses/${SHA} \
-            -d '{
-              "target_url":"'$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID'",
-              "description": "Running e2e",
-              "state": "pending"
-            }'
-  e2e:
-    needs: update-e2e-status
-    runs-on: [self-hosted, headless]
-    strategy:
-      fail-fast: false
-      matrix:
-        protractor-spec: [
-          './src/advanced/urlParsing.prod.e2e-spec.js',
-          './src/advanced/pluginApi.prod.e2e-spec.js',
-          './src/advanced/nonAtlasImages.prod.e2e-spec.js',
-          # './src/advanced/browsingForDatasets.prod.e2e-spec.js',
-          './src/advanced/favDatasets.prod.e2e-spec.js',
-          './src/advanced/history.prod.e2e-spec.js',
-          
-          './src/selecting/region.prod.e2e-spec.js',
-          './src/selecting/template.prod.e2e-spec.js',
-          './src/selecting/atlas.prod.e2e-spec.js',
-
-          './src/layout/home.prod.e2e-spec.js'
-        ]
-    env:
-      PROTRACTOR_SPECS: ${{ matrix.protractor-spec }}
-      ATLAS_URL: ${{ github.event.inputs.url }}
-      PPTR_VERSION: "5.3.1"
-      CHROMIUM_VERSION: "86.0.4240.0"
-
-    outputs:
-      failure-state: ${{ steps.failure-state-step.outputs.failure-state }}
-
-    steps:
-    - uses: actions/checkout@v4
-      with:
-        ref: ${{ github.event.ref }}
-
-    - name: Install dep
-      run: |
-        npm i
-        npm run wd -- update --versions.chrome=${CHROMIUM_VERSION}
-        npm i --no-save puppeteer@${PPTR_VERSION}
-  
-    - name: 'Run e2e for ${{ matrix.protractor-spec }} on ${{ github.event.inputs.url }}'
-      run: npm run e2e
-
-    - name: Set output when workflow fails
-      if: failure()
-      run: echo "failure-state=true" >> $GITHUB_OUTPUT
-      id: failure-state-step
-
-    - name: Define screenshot artefact
-      if: failure()
-      run: |
-        strip_prefix=${PROTRACTOR_SPECS#./src/}
-        strip_suffix=${strip_prefix%.e2e-spec.js}
-        replace_slash=${strip_suffix//\//-}
-        replace_dots=${replace_slash//\./-}
-        echo 'ARTEFACT_NAME='$replace_dots >> $GITHUB_ENV
-
-    - name: 'Upload screenshots artefact'
-      if: failure()
-      uses: actions/upload-artifact@v2
-      with:
-        name: ${{ env.ARTEFACT_NAME }}
-        path: ./scrnsht/
-
-  update-after-e2e-status:
-    if: always()
-    needs: e2e
-    runs-on: ubuntu-latest
-    env:
-      URL_ROOT: https://api.github.com/repos/HumanBrainProject/interactive-viewer
-      SHA: ${{ github.event.inputs.sha }}
-    steps:
-      - name: update badge
-        run: |
-          [[ '${{ needs.e2e.outputs.failure-state }}' = 'true' ]] && state=failure || state=success &&
-          curl -v \
-            -X POST \
-            -H "Authorization: Bearer ${{ github.token }}" \
-            -H 'accept: application/vnd.github.v3+json' \
-            ${URL_ROOT}/statuses/${SHA} \
-            -d '{
-              "target_url":"'$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID'",
-              "description": "e2e completed successfully.",
-              "state": "'$state'"
-            }'
diff --git a/Dockerfile b/Dockerfile
index 2bae7e743c1afab9f08f24ec5ceae9df1fd19846..e5669e328840b8e6fc767ad8a3333ff993a8890f 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,5 +1,8 @@
 FROM node:16 as builder
 
+ARG BUILD_HASH
+ENV BUILD_HASH=${BUILD_HASH:-devbuild}
+
 ARG BACKEND_URL
 ENV BACKEND_URL=${BACKEND_URL}
 
diff --git a/backend/app/app.py b/backend/app/app.py
index 5d8c8be2c6589ccded5769329fea8e6e70786ce4..69ed12ab0cf369e2aed2391b207d8c5dbd091dab 100644
--- a/backend/app/app.py
+++ b/backend/app/app.py
@@ -15,6 +15,7 @@ from app.user import router as user_router
 from app.config import HOST_PATHNAME
 from app.logger import logger
 from app.bkwdcompat import BkwdCompatMW
+from app.version_header import VersionHeaderMW
 
 app = FastAPI()
 
@@ -26,6 +27,7 @@ def ready():
 
 app.add_middleware(SessionMiddleware, secret_key=SESSION_SECRET)
 app.add_middleware(BkwdCompatMW)
+app.add_middleware(VersionHeaderMW)
 
 for vip_route in vip_routes:
     @app.get(f"/{vip_route}")
diff --git a/backend/app/config.py b/backend/app/config.py
index d51631de39d3d3f0b2373a7dd7010e7db6d41f96..42ddbaace8377c189451d9a8dd61448ee5a8bf52 100644
--- a/backend/app/config.py
+++ b/backend/app/config.py
@@ -34,4 +34,6 @@ SXPLR_BUCKET_NAME = os.getenv("SXPLR_BUCKET_NAME", "interactive-atlas-viewer")
 
 LOGGER_DIR = os.getenv("LOGGER_DIR")
 
-PATH_TO_PUBLIC = os.getenv("PATH_TO_PUBLIC", "../dist/aot")
\ No newline at end of file
+PATH_TO_PUBLIC = os.getenv("PATH_TO_PUBLIC", "../dist/aot")
+
+BUILD_HASH = os.getenv("BUILD_HASH", "devbuild")
diff --git a/backend/app/version_header.py b/backend/app/version_header.py
new file mode 100644
index 0000000000000000000000000000000000000000..8ece7c233df70edb79b486311e853ecfd08e7170
--- /dev/null
+++ b/backend/app/version_header.py
@@ -0,0 +1,16 @@
+from fastapi import Request
+from starlette.middleware.base import BaseHTTPMiddleware, RequestResponseEndpoint
+from starlette.responses import Response
+from app.config import BUILD_HASH
+
+class VersionHeaderMW(BaseHTTPMiddleware):
+    async def dispatch(self, request: Request, call_next: RequestResponseEndpoint) -> Response:
+        resp = await call_next(request)
+        if (
+            resp.headers.get("ETag") # if the route sets its own etag, do not interfere
+            or request.method != "GET" # if the request is not a get method do not interfere
+            or (300 <= resp.status_code < 400) # if the request is redirect, do not interfere
+        ):
+            return resp
+        resp.headers["ETag"] = BUILD_HASH
+        return resp
diff --git a/cypress.config.js b/cypress.config.js
new file mode 100644
index 0000000000000000000000000000000000000000..4530a6ef45a09a50e8cc71760953abe3d49b398e
--- /dev/null
+++ b/cypress.config.js
@@ -0,0 +1,16 @@
+const { defineConfig } = require("cypress");
+
+module.exports = defineConfig({
+  e2e: {
+    defaultCommandTimeout: 10000,
+    supportFile: false,
+    setupNodeEvents(on, config) {
+      // implement node event listeners here
+    },
+  },
+  env: {
+    SCREENSHOT_URL: process.env.SCREENSHOT_URL,
+    SCREENSHOT_PATH: process.env.SCREENSHOT_PATH,
+  },
+  experimentalWebKitSupport: !!process.env.USE_SAFARI
+});
diff --git a/cypress/e2e/screenshot.cy.js b/cypress/e2e/screenshot.cy.js
new file mode 100644
index 0000000000000000000000000000000000000000..19e259eac0f2fc50b6dbeaa75cf8cc6c80d5e5b2
--- /dev/null
+++ b/cypress/e2e/screenshot.cy.js
@@ -0,0 +1,22 @@
+const {
+  SCREENSHOT_URL,
+  SCREENSHOT_PATH,
+} = Cypress.env()
+
+describe(`Visiting ${SCREENSHOT_URL}`, () => {
+  it(`Screenshot to ${SCREENSHOT_PATH}`, () => {
+    if (!SCREENSHOT_URL) {
+      console.error(`SCREENSHOT_URL not defined. Exiting`)
+      return
+    }
+
+    cy.visit(SCREENSHOT_URL)
+    cy.wait(10000)
+
+    if (!SCREENSHOT_PATH) {
+      console.error(`SCREENSHOT_PATH not defined. Exiting`)
+      return
+    }
+    cy.screenshot(SCREENSHOT_PATH)
+  })
+})
diff --git a/docs/releases/v2.14.4.md b/docs/releases/v2.14.4.md
index c6ba74a276d284dd2f32a7b2d115ebe2f04c0566..efb0e01efdb12eb7d3665ca369e5c00a1a384aaa 100644
--- a/docs/releases/v2.14.4.md
+++ b/docs/releases/v2.14.4.md
@@ -2,7 +2,7 @@
 
 ## Feature
 
-- Sagittal view of perspective PiP changes hemisphere when user navigates to the otehr hemisphere
+- Sagittal view of perspective PiP changes hemisphere when user navigates to the other hemisphere
 - Adds an additional degree adjustment to perspective PiP
 - Encode maximised panel state
 
diff --git a/docs/releases/v2.14.5.md b/docs/releases/v2.14.5.md
index 233bc752233142b59218fbd48d29db3177033a02..8b2ffba5a6931aa714d5a311acf6c6853373996f 100644
--- a/docs/releases/v2.14.5.md
+++ b/docs/releases/v2.14.5.md
@@ -8,13 +8,13 @@
 - Reworded point assignment UI
 - Allow multi selected region names to be copied
 - Added legend to region hierarchy
-- Allow latest queried concept in feature view
 - Allow experimental flag to be set to be on at runtime (this also shows the button, allow toggling of experimental features)
 - Feature: added supported for .annot fsaverage label
+- allow big brain template to be downloaded
 - (experimental) Added code snippet to limited panels
 - (experimental) allow addition of custom linear coordinate space
 - (experimental) show BigBrain slice number
-- (experimental) allow big brain template to be downloaded
+
 
 ## Bugfix
 
@@ -24,7 +24,6 @@
 
 ## Behind the Scenes
 
-- Removed dependency on connectivity-component
 - Removed reference to JSC OKD instance, as the instance is no longer available
 - Updated google-site-verification
 - Allow inter-space transform to be configured at runtime
diff --git a/docs/releases/v2.14.7.md b/docs/releases/v2.14.7.md
new file mode 100644
index 0000000000000000000000000000000000000000..143702855fe09a2d38b3f5e72790d39711b327ae
--- /dev/null
+++ b/docs/releases/v2.14.7.md
@@ -0,0 +1,12 @@
+# v2.14.7
+
+## Bugfix
+
+- fixed issue on iOS/Safari volumetric viewer not displaying. (update called before config was populated).
+
+## Behind the Scenes
+
+- Minor refactor to remove unneeded code.
+- Fixed typos/errors in release notes
+- Removed unused tests (e2e)
+- Added simple cypress for basic viewer rendering
diff --git a/e2e/chromeOpts.js b/e2e/chromeOpts.js
deleted file mode 100644
index fd9b30a00b9eca3251366ae8667391e5ebb1a6b3..0000000000000000000000000000000000000000
--- a/e2e/chromeOpts.js
+++ /dev/null
@@ -1,12 +0,0 @@
-const { width, height } = require('./opts')
-
-module.exports = [
-  ...(process.env.DISABLE_CHROME_HEADLESS ?  [] : ['--headless']),
-  '--no-sandbox',
-  ...(process.env.ENABLE_GPU ? []: ['--disable-gpu']),
-  '--disable-setuid-sandbox',
-  "--disable-extensions",
-  '--disable-dev-shm-usage',
-  `--window-size=${width},${height}`,
-  '--disable-application-cache'
-]
\ No newline at end of file
diff --git a/e2e/opts.js b/e2e/opts.js
deleted file mode 100644
index 9b75d287f6ec4ffa0100562d033d65b1eb9c4eb6..0000000000000000000000000000000000000000
--- a/e2e/opts.js
+++ /dev/null
@@ -1,4 +0,0 @@
-module.exports = {
-  width: 800,
-  height: 796
-}
diff --git a/e2e/protractor.conf.js b/e2e/protractor.conf.js
deleted file mode 100644
index 2fbc49e5b62647cd050e47ea1fa2dc513c80753d..0000000000000000000000000000000000000000
--- a/e2e/protractor.conf.js
+++ /dev/null
@@ -1,134 +0,0 @@
-
-// n.b. to start selenium, run npm run wd -- update && npm run wd -- start
-// n.b. you will need to run `npm i --no-save puppeteer`, so that normal download script does not download chrome binary
-const chromeOpts = require('./chromeOpts')
-const fs = require('fs')
-const path = require('path')
-const { promisify } = require('util')
-const asyncWrite = promisify(fs.writeFile)
-const asyncMkdir = promisify(fs.mkdir)
-
-const SELENIUM_ADDRESS = process.env.SELENIUM_ADDRESS
-
-const {
-  BROWSERSTACK_TEST_NAME,
-  BROWSERSTACK_USERNAME,
-  BROWSERSTACK_ACCESS_KEY,
-} = process.env
-const directConnect = !!process.env.DIRECT_CONNECT
-
-const PROTRACTOR_SPECS = process.env.PROTRACTOR_SPECS
-
-const localConfig = {
-  ...(SELENIUM_ADDRESS
-    ? { seleniumAddress: SELENIUM_ADDRESS }
-    : { directConnect: true }
-  ),
-  capabilities: {
-    // Use headless chrome
-    browserName: 'chrome',
-    'goog:chromeOptions': {
-      args: [
-        ...chromeOpts
-      ],
-      ...(
-        SELENIUM_ADDRESS
-          ? {}
-          : { binary: (() => require('puppeteer').executablePath())() }
-      )
-    }
-  },
-  onPrepare: function() {
-    // polyfill for node10 or lower
-    if (typeof globalThis === 'undefined') global.globalThis = {}
-    jasmine.getEnv().addReporter({
-      specDone: async ({ status, id, message, fullName, ...rest }) => {
-        if (status === 'failed') {
-          console.log(`spec failed, taking screenshot`)
-          const b64 = await globalThis.IAVBase.takeScreenshot()
-          const dir = './scrnsht/'
-          await asyncMkdir(dir, { recursive: true })
-          await asyncWrite(
-            path.join(dir, `${id}.png`),
-            b64,
-            'base64'
-          )
-          await asyncWrite(
-            path.join(dir, `${id}.txt`),
-            JSON.stringify({ id, status, message, fullName }, null, 2),
-            'utf-8'
-          )
-        }
-      }
-    })
-  }
-}
-
-
-const { Local } = require('browserstack-local');
-
-let bsLocal
-/**
- * config adapted from
- * https://github.com/browserstack/protractor-browserstack
- *
- * MIT licensed
- */
-const bsConfig = {
-  'browserstackUser': BROWSERSTACK_USERNAME,
-  'browserstackKey': BROWSERSTACK_ACCESS_KEY,
-
-  'capabilities': {
-    'build': 'protractor-browserstack',
-    'name': BROWSERSTACK_TEST_NAME || 'iav_e2e',
-    "os" : "Windows",
-    "osVersion" : "10",
-    'browserName': 'chrome',
-    'browserstack.local': true,
-    "seleniumVersion" : "4.0.0-alpha-2",
-    'browserstack.debug': 'true'
-  },
-  "browserName" : "Chrome",
-  "browserVersion" : "83.0",
-
-  // Code to start browserstack local before start of test
-  beforeLaunch: function(){
-    console.log("Connecting local");
-    return new Promise(function(resolve, reject){
-      bsLocal = new Local();
-      bsLocal.start({'key': BROWSERSTACK_ACCESS_KEY }, function(error) {
-        if (error) return reject(error);
-        console.log('Connected. Now testing...');
-
-        resolve();
-      });
-    });
-  },
-
-  // Code to stop browserstack local after end of test
-  afterLaunch: function(){
-    return new Promise(function(resolve, reject){
-      if (bsLocal) bsLocal.stop(resolve)
-      else resolve()
-    });
-  }
-}
-
-exports.config = {
-  specs: [
-    PROTRACTOR_SPECS || './src/**/*.prod.e2e-spec.js'
-  ],
-  jasmineNodeOpts: {
-    defaultTimeoutInterval: 1000 * 60 * 10
-  },
-
-  ...(
-    BROWSERSTACK_ACCESS_KEY && BROWSERSTACK_USERNAME
-    ? bsConfig
-    : localConfig
-  ),
-
-  ...(
-    (directConnect && { directConnect }) || {}
-  )
-}
diff --git a/e2e/screenshots/gen.js b/e2e/screenshots/gen.js
deleted file mode 100644
index 00533c07e64883ade9e0270bcfaa0c87fc7b2155..0000000000000000000000000000000000000000
--- a/e2e/screenshots/gen.js
+++ /dev/null
@@ -1,29 +0,0 @@
-const { spawn } = require("child_process")
-const path = require('path')
-const glob = require('glob')
-describe('> generating screenshot', () => {
-  let childProcess
-  const matchCwdPath = path.join(__dirname, '../src')
-  const matches = glob.sync('**/*.e2e-screenshot.js', { cwd: matchCwdPath })
-  const cwdPath = path.join(__dirname, '../../deploy/')
-  
-  beforeAll(done => {
-    throw "Need to reimplement. backend is rewritten from node to python"
-    childProcess = spawn('node', ['server.js'],  {
-      cwd: cwdPath,
-      env: {
-        ...process.env,
-        BUILD_TEXT: ''
-      }
-    })
-    setTimeout(done, 1000)
-  })
-
-  for (const match of matches) {
-    const requirePath = path.join(matchCwdPath, match)
-    require(requirePath)
-  }
-  afterAll(() => {
-    childProcess.kill()
-  })
-})
diff --git a/e2e/setup.sh b/e2e/setup.sh
deleted file mode 100755
index 08597d425532f91194cacfc3e54d72e689c85e88..0000000000000000000000000000000000000000
--- a/e2e/setup.sh
+++ /dev/null
@@ -1,6 +0,0 @@
-#! /bin/bash
-
-export CHROMIUM_VERSION=80.0.3987.106
-export PPTR_VERSION=2.1.0
-npm run wd -- update --versions.chrome=${CHROMIUM_VERSION}
-npm i --no-save puppeteer@${PPTR_VERSION}
\ No newline at end of file
diff --git a/e2e/src/advanced/browsingForDatasets.prod.e2e-spec.js b/e2e/src/advanced/browsingForDatasets.prod.e2e-spec.js
deleted file mode 100644
index 56d74d804db8c2b908541a0dcdc7accf161c158d..0000000000000000000000000000000000000000
--- a/e2e/src/advanced/browsingForDatasets.prod.e2e-spec.js
+++ /dev/null
@@ -1,157 +0,0 @@
-const { AtlasPage } = require('../util')
-const { CONST, ARIA_LABELS } = require('../../../common/constants')
-const { retry } = require('../../../common/util')
-
-const {
-  RECORDING_FLAG
-} = process.env
-
-const atlasName = `Multilevel Human Atlas`
-
-const templates = [
-  'MNI Colin 27',
-  'ICBM 152 2009c Nonlinear Asymmetric'
-]
-
-const newShouldHaveReceptor = [
-  ["Area 4p (PreCG)", 1, 1, 1],
-  ["Area 3b (PostCG)", 1, 1, 1],
-  ["DG (Hippocampus)", 0, 0, 1],
-  ["Area FG2 (FusG)", 0, 1, 1],
-  ["Area hOc1 (V1, 17, CalcS)" ,1,  1, 1],
-  ["Area PFm (IPL)", 0, 1, 1],
-  ["Area 44 (IFG)", 0, 0, 1],
-  ["CA3 (Hippocampus)", 0, 0, 1],
-  ["CA2 (Hippocampus)", 0, 0, 1],
-  ["CA1 (Hippocampus)", 0, 0, 1],
-  ["Area PGp (IPL)", 0, 0, 1],
-  ["CA1 (Hippocampus)", 0, 0, 1],
-  ["Area 45 (IFG)", 1, 1, 1],
-  ["Area hOc3v (LingG)", 0, 0, 1],
-  ["Area hOc3d (Cuneus)", 0, 0, 1],
-  ["Area 7A (SPL)", 1, 1, 1],
-  ["Area 44 (IFG)", 1, 1, 1],
-  ["Area hOc2 (V2, 18)", 0, 0, 1],
-  ["Area PFop (IPL)", 0, 0, 1],
-  ["Area PF (IPL)", 0, 0, 1],
-  ["CA2 (Hippocampus)", 0, 0, 1],
-  ["Area PFt (IPL)", 0, 0, 1],
-  ["Area TE 2.1 (STG)", 0, 0, 1],
-  ["Area PFcm (IPL)", 0, 0, 1],
-  ["CA3 (Hippocampus)", 0, 0, 1],
-  ["DG (Hippocampus)", 0, 0, 1],
-  ["CA3 (Hippocampus)", 0, 0, 1],
-  ["CA2 (Hippocampus)", 0, 0, 1],
-  ["CA1 (Hippocampus)", 0, 0, 1],
-  ["CA3 (Hippocampus)", 0, 0, 1],
-  ["CA2 (Hippocampus)", 0, 0, 1],
-  ["CA1 (Hippocampus)", 0, 0, 1],
-  ["Area FG1 (FusG)", 0, 1, 1],
-  ["CA3 (Hippocampus)", 0, 0, 1],
-  ["Area TE 1.0 (HESCHL)", 0, 0, 1],
-  ["CA1 (Hippocampus)", 0, 0, 1],
-  ["Area hOc2 (V2, 18)", 0, 0, 1],
-  ["CA2 (Hippocampus)", 0, 0, 1],
-  ["CA3 (Hippocampus)", 0, 0, 1],
-  ["CA2 (Hippocampus)", 0, 0, 1],
-  ["CA1 (Hippocampus)", 0, 0, 1],
-  ["Area PGa (IPL)", 0, 0, 1],
-].reduce((acc, curr) => {
-  const [ name, pr, ar, fp ] = curr
-  const foundIdx = acc.findIndex(([ accName ]) => name === accName )
-  return foundIdx >= 0
-    ? acc.map((el, idx) => idx === foundIdx
-      ? [ name, el[1] + pr, el[2] + ar, el[3] + fp ]
-      : el)
-    : acc.concat([curr])
-  
-}, [])
-
-
-describe('> dataset browser', () => {
-  let iavPage
-  beforeAll(async () => {
-    iavPage = new AtlasPage()
-    await iavPage.init()
-  })
-
-  for (const template of templates) {
-    describe(`> in template: ${template}`, () => {
-      beforeAll(async () => {
-        await iavPage.goto()
-        await iavPage.setAtlasSpecifications(atlasName, [ template ])
-
-        // account for linear template translation backend
-        await iavPage.wait(5000)
-        await iavPage.waitUntilAllChunksLoaded()
-      })
-
-      afterEach(async () => {
-        try {
-          await iavPage.click(`[aria-label="${ARIA_LABELS.CLOSE}"]`)
-        } catch (e) {
-
-        }
-      })
-      for (const [ area, ...rest ] of newShouldHaveReceptor) {
-        it(`> receptor data ${area} should be able to be found`, async () => {
-          await iavPage.searchRegionWithText(area)
-          await iavPage.wait(2000)
-          await iavPage.selectSearchRegionAutocompleteWithText()
-          await retry(async () => {
-            await iavPage.dismissModal()
-            await iavPage.toggleExpansionPanelState(`${CONST.REGIONAL_FEATURES}`, true)
-          }, {
-            timeout: 2000,
-            retries: 10
-          })
-          await iavPage.wait(2000)
-          await iavPage.waitUntilAllChunksLoaded()
-          await iavPage.dismissModal()
-          const datasets = await iavPage.getVisibleDatasets()
-          const receptorDsIdx = datasets.findIndex(ds => ds.toLowerCase().indexOf('receptor') >= 0)
-          expect(receptorDsIdx).toBeGreaterThanOrEqual(0)
-
-          if (RECORDING_FLAG) {
-            await iavPage.clickNthDataset(receptorDsIdx)
-            await iavPage.wait(1000)
-            await iavPage.toggleExpansionPanelState(/receptor/i, true)
-            await iavPage.wait(5000)
-          }
-        })
-      }
-    })
-  }
-
-  describe('> modality filter', () => {
-    beforeAll(async () => {
-      await iavPage.goto()
-      await iavPage.setAtlasSpecifications(atlasName, [ templates[0] ])
-
-      await iavPage.wait(5000)
-      await iavPage.waitUntilAllChunksLoaded()
-      await iavPage.searchRegionWithText(newShouldHaveReceptor[0][0])
-      await iavPage.wait(2000)
-      await iavPage.selectSearchRegionAutocompleteWithText()
-      await retry(async () => {
-        await iavPage.dismissModal()
-        await iavPage.toggleExpansionPanelState(`${CONST.REGIONAL_FEATURES}`, true)
-      }, {
-        timeout: 2000,
-        retries: 10
-      })
-      await iavPage.dismissModal()
-      await iavPage.wait(2000)
-      await iavPage.waitUntilAllChunksLoaded()
-    })
-
-    it('> should be populated', async () => {
-      await iavPage.click(`[aria-label="${ARIA_LABELS.MODALITY_FILTER}"]`)
-      const text = await iavPage.getText(`[aria-label="${ARIA_LABELS.LIST_OF_MODALITIES}"]`)
-      const re = /\(\d+\)/.exec(text)
-      expect(
-        re
-      ).toBeTruthy()
-    })
-  })
-})
diff --git a/e2e/src/advanced/favDatasets.prod.e2e-spec.js b/e2e/src/advanced/favDatasets.prod.e2e-spec.js
deleted file mode 100644
index ec5de6d63b1b5a84f080def6072457c218f0235c..0000000000000000000000000000000000000000
--- a/e2e/src/advanced/favDatasets.prod.e2e-spec.js
+++ /dev/null
@@ -1,251 +0,0 @@
-const { AtlasPage } = require('../util')
-const { ARIA_LABELS, CONST } = require('../../../common/constants')
-const { retry } = require('../../../common/util')
-
-const atlasName = `Multilevel Human Atlas`
-
-const templates = [
-  'MNI Colin 27',
-  'ICBM 152 2009c Nonlinear Asymmetric'
-]
-
-const area = 'Area hOc1 (V1, 17, CalcS)'
-
-const receptorName = `Density measurements of different receptors for Area hOc1 (V1, 17, CalcS) [human, v1.0]`
-const ieegDatasetName = `Human Intracranial EEG Database (HID) [cohort I]`
-
-// TODO finish writing tests
-describe(`fav'ing dataset`, () => {
-  let iavPage = new AtlasPage()
-  beforeEach(async () => {
-    iavPage = new AtlasPage()
-    await iavPage.init()
-    await iavPage.goto()
-    await iavPage.setAtlasSpecifications(atlasName, [ templates[1] ])
-
-    // account for linear template translation backend
-    await iavPage.wait(5000)
-    await iavPage.waitUntilAllChunksLoaded()
-
-    await iavPage.searchRegionWithText(area)
-    await iavPage.wait(2000)
-    await iavPage.selectSearchRegionAutocompleteWithText()
-    await retry(async () => {
-      await iavPage.dismissModal()
-      await iavPage.toggleExpansionPanelState(`${CONST.REGIONAL_FEATURES}`, true)
-    }, {
-      timeout: 2000,
-      retries: 10
-    })
-
-    await iavPage.wait(1000)
-    await iavPage.waitUntilAllChunksLoaded()
-    await iavPage.clearAlerts()
-  })
-
-  afterEach(async () => {
-    /**
-     * clear all fav'ed datasets
-     */
-    
-     await iavPage.execScript(`window.localStorage.clear()`)
-  })
-
-  it('> dataset can be fav ed from result panel', async () => {
-
-    const datasets = await iavPage.getVisibleDatasets()
-
-    const receptorIndex = datasets.indexOf(receptorName)
-    const probMap = datasets.indexOf(ieegDatasetName)
-    expect(receptorIndex).toBeGreaterThanOrEqual(0)
-    expect(probMap).toBeGreaterThanOrEqual(0)
-
-    await iavPage.togglePinNthDataset(receptorIndex)
-    await iavPage.wait(500)
-    const txt = await iavPage.getSnackbarMessage()
-    expect(txt).toEqual(`Pinned dataset: ${receptorName}`)
-    
-    await iavPage.togglePinNthDataset(probMap)
-    await iavPage.wait(500)
-    const txt2 = await iavPage.getSnackbarMessage()
-    expect(txt2).toEqual(`Pinned dataset: ${ieegDatasetName}`)
-  })
-
-  describe('> fav dataset list', () => {
-    beforeEach(async () => {
-
-      const datasets = await iavPage.getVisibleDatasets()
-
-      const receptorIndex = datasets.indexOf(receptorName)
-      const probMap = datasets.indexOf(ieegDatasetName)
-
-      await iavPage.togglePinNthDataset(receptorIndex)
-      await iavPage.togglePinNthDataset(probMap)
-    })
-
-    it('> fav ed dataset is visible on UI', async () => {
-      const content = await iavPage.getBadgeContentByDesc(CONST.PINNED_DATASETS_BADGE_DESC)
-      expect(content).toEqual('2')
-    })
-
-    it('> click unpin in fav data panel unpins, but also allow user to undo', async () => {
-      await iavPage.showPinnedDatasetPanel()
-      await iavPage.wait(1000)
-      const textsArr = await iavPage.getBottomSheetList()
-      const idx = textsArr.indexOf(receptorName)
-      if (idx < 0) throw new Error(`index of receptor name not found: ${receptorName}: ${textsArr}`)
-      await iavPage.clickNthItemFromBottomSheetList(idx, `[aria-label="Toggle pinning this dataset"]`)
-      await iavPage.wait(500)
-  
-      const txt = await iavPage.getSnackbarMessage()
-      expect(txt).toEqual(`Unpinned dataset: ${receptorName}`)
-  
-      const content = await await iavPage.getBadgeContentByDesc(CONST.PINNED_DATASETS_BADGE_DESC)
-      expect(content).toEqual('1')
-
-      await iavPage.clickSnackbarAction()
-      await iavPage.wait(500)
-
-      const textsArr3 = await iavPage.getBottomSheetList()
-      const content2 = await await iavPage.getBadgeContentByDesc(CONST.PINNED_DATASETS_BADGE_DESC)
-      expect(content2).toEqual('2')
-      expect(
-        textsArr3.indexOf(receptorName)
-      ).toBeGreaterThanOrEqual(0)
-
-    })
-
-    // TODO effectively test the bulk dl button
-    // it('> if fav dataset >=1, bulk dl btn is visible', async () => {
-
-    // })
-  })
-
-  describe('> fav functionality in detailed dataset panel', () => {
-
-    it('> click pin in dataset detail sheet pins fav, but also allows user to undo', async () => {
-      const datasets = await iavPage.getVisibleDatasets()
-
-      const receptorIndex = datasets.indexOf(receptorName)
-      await iavPage.clickNthDataset(receptorIndex)
-      await iavPage.wait(500)
-
-      // specificity is required, because single dataset card for julich brain also can be selected, and will be clicked and fail this test
-      await iavPage.click(`[aria-label="${ARIA_LABELS.PIN_DATASET}"]`)
-      await iavPage.wait(500)
-
-      const txt = await iavPage.getSnackbarMessage()
-      expect(txt).toEqual(`Pinned dataset: ${receptorName}`)
-
-      const content = await await iavPage.getBadgeContentByDesc(CONST.PINNED_DATASETS_BADGE_DESC)
-      expect(content).toEqual('1')
-
-      await iavPage.clickSnackbarAction()
-      await iavPage.wait(500)
-
-      const text = await await iavPage.getBadgeContentByDesc(CONST.PINNED_DATASETS_BADGE_DESC)
-      expect(text).toBeFalsy()
-    })
-
-    it('> click unpin in dataset detail sheet unpins fav, but also allows user to undo', async () => {
-
-      const datasets = await iavPage.getVisibleDatasets()
-
-      const receptorIndex = datasets.indexOf(receptorName)
-      await iavPage.clickNthDataset(receptorIndex)
-      await iavPage.wait(500)
-
-      // specificity is required, because single dataset card for julich brain also can be selected, and will be clicked and fail this test
-      await iavPage.click(`[aria-label="${ARIA_LABELS.PIN_DATASET}"]`)
-      await iavPage.wait(500)
-
-      const numberOfFav = await await iavPage.getBadgeContentByDesc(CONST.PINNED_DATASETS_BADGE_DESC)
-      expect(numberOfFav).toEqual('1')
-      
-      // this wait is unfortunately necessary, as the snack bar sometimes obscures the unpin this dataset button	
-      await iavPage.wait(5000)
-
-      // specificity is required, because single dataset card for julich brain also can be selected, and will be clicked and fail this test
-      await iavPage.click(`[aria-label="${ARIA_LABELS.PIN_DATASET}"]`)
-      await iavPage.wait(500)
-
-      const txt = await iavPage.getSnackbarMessage()
-      expect(txt).toEqual(`Unpinned dataset: ${receptorName}`)
-
-      const text = await await iavPage.getBadgeContentByDesc(CONST.PINNED_DATASETS_BADGE_DESC)
-      expect(text).toBeFalsy()
-      
-      await iavPage.clickSnackbarAction()
-      await iavPage.wait(500)
-
-      const numberOfFav2 = await await iavPage.getBadgeContentByDesc(CONST.PINNED_DATASETS_BADGE_DESC)
-      expect(numberOfFav2).toEqual('1')
-    })
-  
-  })
-
-  describe('> access via collection', () => {
-    beforeEach(async () => {
-
-      const datasets = await iavPage.getVisibleDatasets()
-
-      const receptorIndex = datasets.indexOf(receptorName)
-      const probMap = datasets.indexOf(ieegDatasetName)
-
-      await iavPage.togglePinNthDataset(receptorIndex)
-      await iavPage.togglePinNthDataset(probMap)
-    })
-
-    it('> clicking pin shows collection of pinned datasets', async () => {
-
-      await iavPage.showPinnedDatasetPanel()
-      await iavPage.wait(500)
-      const textsArr = await iavPage.getBottomSheetList()
-      
-      expect(textsArr.length).toEqual(2)
-      expect(textsArr).toContain(receptorName)
-      expect(textsArr).toContain(ieegDatasetName)
-    })
-
-    it('> dataset detail can be launched via collection', async () => {
-      await iavPage.showPinnedDatasetPanel()
-      const textsArr = await iavPage.getBottomSheetList()
-      const idx = textsArr.findIndex(t => t === receptorName)
-      expect(idx).toBeGreaterThanOrEqual(0)
-      await iavPage.clickNthItemFromBottomSheetList(idx)
-      await iavPage.wait(1000)
-      const modalText = await iavPage.getModalText()
-      expect(modalText.length).toBeGreaterThan(1e3)
-    })
-
-    it('> dataset can be pinned/unpinned via collection', async () => {
-      await iavPage.showPinnedDatasetPanel()
-      const textsArr = await iavPage.getBottomSheetList()
-      const idx = textsArr.findIndex(t => t === receptorName)
-      await iavPage.clickNthItemFromBottomSheetList(idx)
-      await iavPage.wait(1000)
-
-      /**
-       * for now, from collection, a modal is launched
-       */
-      await iavPage.click(`mat-dialog-container [aria-label="${ARIA_LABELS.PIN_DATASET}"]`)
-      await iavPage.wait(1000)
-      const txt = await iavPage.getSnackbarMessage()
-      expect(txt).toEqual(`Unpinned dataset: ${receptorName}`)
-
-      const content = await await iavPage.getBadgeContentByDesc(CONST.PINNED_DATASETS_BADGE_DESC)
-      expect(content).toEqual('1')
-
-      await iavPage.wait(5000)
-
-      await iavPage.click(`mat-dialog-container [aria-label="${ARIA_LABELS.PIN_DATASET}"]`)
-      await iavPage.wait(1000)
-      const txt2 = await iavPage.getSnackbarMessage()
-      expect(txt2).toEqual(`Pinned dataset: ${receptorName}`)
-
-      const content2 = await await iavPage.getBadgeContentByDesc(CONST.PINNED_DATASETS_BADGE_DESC)
-      expect(content2).toEqual('2')
-
-    })
-  })
-})
diff --git a/e2e/src/advanced/history.prod.e2e-spec.js b/e2e/src/advanced/history.prod.e2e-spec.js
deleted file mode 100644
index c8cf1a937391989f4ec8628268e91478e4d91bde..0000000000000000000000000000000000000000
--- a/e2e/src/advanced/history.prod.e2e-spec.js
+++ /dev/null
@@ -1,60 +0,0 @@
-const { WdIavPage } = require('../../util/selenium/iav')
-const { AtlasPage } = require('../util')
-const { height, width } = require("../../opts")
-const atlasName = `Multilevel Human Atlas`
-
-describe('> navigating IAV via history', () => {
-  let iavPage = new AtlasPage()
-  beforeEach(async () => {
-    iavPage = new AtlasPage()
-    await iavPage.init()
-    await iavPage.goto()
-    await iavPage.setAtlasSpecifications(atlasName)
-    
-    await iavPage.wait(5000)
-    await iavPage.waitUntilAllChunksLoaded()
-  })
-
-  it('> after navigate, navigation state differs', async () => {
-    const nav = await iavPage.getNavigationState()
-    await iavPage.cursorMoveToAndDrag({
-      position: [ Math.round(width / 4), Math.round(height / 4) ],
-      delta: [ Math.round(width / 8), Math.round(height / 8) ]
-    })
-    const nav2 = await iavPage.getNavigationState()
-
-    // expect some positions to change after dragging
-    expect(
-      nav.position.some((v, idx) => v !== nav2.position[idx])
-    ).toBeTrue()
-  })
-
-  it('> after navigate, history back, navigation should ', async () => {
-    const nav = await iavPage.getNavigationState()
-    await iavPage.cursorMoveToAndDrag({
-      position: [ Math.round(width / 4), Math.round(height / 4) ],
-      delta: [ Math.round(width / 8), Math.round(height / 8) ]
-    })
-    await iavPage.wait(5000)
-    await iavPage.historyBack()
-    await iavPage.wait(5000)
-
-    const nav2 = await iavPage.getNavigationState()
-    // expect some positions to change after dragging
-    expect(
-      nav.position.every((v, idx) => v === nav2.position[idx])
-    ).toBeTrue()
-  })
-
-  it('> history back, viewer should despawn ', async () => {
-
-    await iavPage.wait(5000)
-    await iavPage.historyBack()
-    await iavPage.wait(5000)
-
-    const flag = await iavPage.viewerIsPopulated()
-    expect(flag).toBeFalse()
-
-  })
-
-})
\ No newline at end of file
diff --git a/e2e/src/advanced/nonAtlasImages.prod.e2e-spec.js b/e2e/src/advanced/nonAtlasImages.prod.e2e-spec.js
deleted file mode 100644
index 3277e69e5a4328233addc63260b9fd06e876eb5b..0000000000000000000000000000000000000000
--- a/e2e/src/advanced/nonAtlasImages.prod.e2e-spec.js
+++ /dev/null
@@ -1,236 +0,0 @@
-const { AtlasPage } = require('../util')
-const { URLSearchParams } = require('url')
-const { ARIA_LABELS } = require('../../../common/constants')
-describe('> non-atlas images', () => {
-  let iavPage
-
-  beforeAll(async () => {
-    iavPage = new AtlasPage()
-    await iavPage.init()
-  })
-  describe('> standalone volumes', () => {
-
-    // TODO investigates why it occassionally fails
-    it('> loads standalone volumes when set (fails sometimes. Just rerun if it does.)', async () => {
-      const searchParam = new URLSearchParams()
-      searchParam.set('standaloneVolumes', '["precomputed://https://object.cscs.ch/v1/AUTH_08c08f9f119744cbbf77e216988da3eb/imgsvc-46d9d64f-bdac-418e-a41b-b7f805068c64"]')
-      await iavPage.goto(`/?${searchParam.toString()}`, { interceptHttp: true, doNotAutomate: true })
-      await iavPage.wait(10000)
-      const interceptedCalls = await iavPage.getInterceptedHttpCalls()
-      expect(
-        interceptedCalls
-      ).toContain(
-        jasmine.objectContaining(
-          {
-            method: 'GET',
-            url: 'https://object.cscs.ch/v1/AUTH_08c08f9f119744cbbf77e216988da3eb/imgsvc-46d9d64f-bdac-418e-a41b-b7f805068c64/info'
-          }
-        )
-      )
-    })
-
-    it('> if there exist both standalone volumes & xyz template selected, template selected is ignored', async () => {
-      const searchParam = new URLSearchParams()
-      searchParam.set('templateSelected', 'Big Brain (Histology)')
-      searchParam.set('parcellationSelected', 'Cytoarchitectonic Maps')
-      searchParam.set('standaloneVolumes', '["precomputed://https://object.cscs.ch/v1/AUTH_08c08f9f119744cbbf77e216988da3eb/imgsvc-46d9d64f-bdac-418e-a41b-b7f805068c64"]')
-
-      await iavPage.goto(`/?${searchParam.toString()}`, { interceptHttp: true, doNotAutomate: true })
-      await iavPage.wait(30000)
-      const interceptedCalls = await iavPage.getInterceptedHttpCalls()
-
-      expect(
-        interceptedCalls
-      ).toContain(
-        jasmine.objectContaining(
-          {
-            method: 'GET',
-            url: 'https://object.cscs.ch/v1/AUTH_08c08f9f119744cbbf77e216988da3eb/imgsvc-46d9d64f-bdac-418e-a41b-b7f805068c64/info'
-          }
-        )
-      )
-
-      expect(
-        interceptedCalls
-      ).not.toContain(
-        jasmine.objectContaining(
-          {
-            method: 'GET',
-            url: 'https://neuroglancer.humanbrainproject.org/precomputed/BigBrainRelease.2015/8bit/info'
-          }
-        )
-      )
-    })
-  })
-
-  describe('> registered volumes', () => {
-    it('> if ref tmpl is right, should load both tmpl and volume', async () => {
-
-      const searchParam = new URLSearchParams()
-      searchParam.set('templateSelected', 'Big Brain (Histology)')
-      searchParam.set('parcellationSelected', 'Grey/White matter')
-  
-      const previewingDatasetFiles = [
-        {
-          "datasetId":"minds/core/dataset/v1.0.0/b08a7dbc-7c75-4ce7-905b-690b2b1e8957",
-          "filename":"Overlay of data modalities"
-        }
-      ]
-      searchParam.set('previewingDatasetFiles', JSON.stringify(previewingDatasetFiles))
-      
-      await iavPage.goto(`/?${searchParam.toString()}`, { interceptHttp: true, doNotAutomate: true })
-      await iavPage.wait(30000)
-      const interceptedCalls = await iavPage.getInterceptedHttpCalls()
-
-      const array = [
-        "PLI Fiber Orientation Red Channel",
-        "PLI Fiber Orientation Green Channel",
-        "PLI Fiber Orientation Blue Channel",
-        "Blockface Image",
-        "PLI Transmittance",
-        "T2w MRI",
-        "MRI Labels"
-      ]
-
-      expect(
-        interceptedCalls
-      ).toContain(
-        jasmine.objectContaining(
-          {
-            method: 'GET',
-            url: 'https://neuroglancer.humanbrainproject.org/precomputed/BigBrainRelease.2015/8bit/info'
-          }
-        )
-      )
-
-      const arrPli = [
-        "https://neuroglancer.humanbrainproject.eu/precomputed/PLI_FOM/BI-FOM-HSV_R",
-        "https://neuroglancer.humanbrainproject.eu/precomputed/PLI_FOM/BI-FOM-HSV_G",
-        "https://neuroglancer.humanbrainproject.eu/precomputed/PLI_FOM/BI-FOM-HSV_B",
-        "https://neuroglancer.humanbrainproject.eu/precomputed/PLI_FOM/BI",
-        "https://neuroglancer.humanbrainproject.eu/precomputed/PLI_FOM/BI-TIM",
-        "https://neuroglancer.humanbrainproject.eu/precomputed/PLI_FOM/BI-MRI",
-        "https://neuroglancer.humanbrainproject.eu/precomputed/PLI_FOM/BI-MRS",
-      ]
-
-      expect(
-        interceptedCalls
-      ).toContain(
-        jasmine.objectContaining(
-          {
-            method: 'GET',
-            url: 'https://neuroglancer.humanbrainproject.org/precomputed/BigBrainRelease.2015/8bit/info'
-          }
-        )
-      )
-
-      for (const url of arrPli) {
-        expect(
-          interceptedCalls
-        ).toContain(
-          jasmine.objectContaining(
-            {
-              method: 'GET',
-              url: `${url}/info`
-            }
-          )
-        )
-      }
-    })
-
-    it('> if ref tmpl is not right, only tmpl is loaded', async () => {
-      const searchParam = new URLSearchParams()
-      searchParam.set('templateSelected', 'MNI Colin 27')
-      searchParam.set('parcellationSelected', 'JuBrain Cytoarchitectonic Atlas')
-  
-      const previewingDatasetFiles = [
-        {
-          "datasetId":"minds/core/dataset/v1.0.0/b08a7dbc-7c75-4ce7-905b-690b2b1e8957",
-          "filename":"Overlay of data modalities"
-        }
-      ]
-      searchParam.set('previewingDatasetFiles', JSON.stringify(previewingDatasetFiles))
-      
-      await iavPage.goto(`/?${searchParam.toString()}`, { interceptHttp: true, doNotAutomate: true })
-      await iavPage.wait(10000)
-      const interceptedCalls = await iavPage.getInterceptedHttpCalls()
-
-      expect(
-        interceptedCalls
-      ).not.toContain(
-        jasmine.objectContaining(
-          {
-            method: 'GET',
-            url: 'https://zam10143.zam.kfa-juelich.de/chumni/nifti/5c38faad1b0deab8d1674248b0107cd3637faa46a88e7a039c511163/BI-TIM/info'
-          }
-        )
-      )
-
-      expect(
-        interceptedCalls
-      ).toContain(
-        jasmine.objectContaining(
-          {
-            method: 'GET',
-            url: 'https://neuroglancer.humanbrainproject.org/precomputed/JuBrain/v2.2c/colin27_seg/info'
-          }
-        )
-      )
-    })
-  
-  })
-
-  describe('> controls for non atlas volumes', () => {
-    it('if no additional volume is being shown, additional volume control is not visible', async () => {
-      const searchParam = new URLSearchParams()
-      searchParam.set('templateSelected', 'MNI Colin 27')
-      searchParam.set('parcellationSelected', 'JuBrain Cytoarchitectonic Atlas')
-  
-      const previewingDatasetFiles = [
-        {
-          "datasetId":"minds/core/dataset/v1.0.0/b08a7dbc-7c75-4ce7-905b-690b2b1e8957",
-          "filename":"Overlay of data modalities"
-        }
-      ]
-      searchParam.set('previewingDatasetFiles', JSON.stringify(previewingDatasetFiles))
-      
-      await iavPage.goto(`/?${searchParam.toString()}`)
-      await iavPage.wait(2000)
-
-      try {
-        const additionalLayerControlIsShown = await iavPage.isVisible(`[aria-label="${ARIA_LABELS.ADDITIONAL_VOLUME_CONTROL}"]`)
-        expect(additionalLayerControlIsShown).toEqual(false)
-      } catch (e) {
-        /**
-         * error when css querying additional volume control
-         * expected behaviour, when it is not visible
-         */
-      }
-      
-    })
-
-    it('if additonal volumes are being shown, additional volume control is visible', async () => {
-      
-      const searchParam = new URLSearchParams()
-      searchParam.set('templateSelected', 'Big Brain (Histology)')
-      searchParam.set('parcellationSelected', 'Grey/White matter')
-  
-      const previewingDatasetFiles = [
-        {
-          "datasetId":"minds/core/dataset/v1.0.0/b08a7dbc-7c75-4ce7-905b-690b2b1e8957",
-          "filename":"Overlay of data modalities"
-        }
-      ]
-      searchParam.set('previewingDatasetFiles', JSON.stringify(previewingDatasetFiles))
-      
-      await iavPage.goto(`/?${searchParam.toString()}`, { forceTimeout: 20000 })
-      await iavPage.wait(2000)
-      
-      const additionalLayerCtrlIsExpanded2 = await iavPage.isVisible(`[aria-label="${ARIA_LABELS.ADDITIONAL_VOLUME_CONTROL}"]`)
-      expect(additionalLayerCtrlIsExpanded2).toEqual(true)
-
-    })
-
-  })
-
-})
diff --git a/e2e/src/advanced/pluginApi.prod.e2e-spec.js b/e2e/src/advanced/pluginApi.prod.e2e-spec.js
deleted file mode 100644
index 3abcab7e33d34fbd737699e18360a4f750af662b..0000000000000000000000000000000000000000
--- a/e2e/src/advanced/pluginApi.prod.e2e-spec.js
+++ /dev/null
@@ -1,170 +0,0 @@
-const { AtlasPage } = require('../util')
-const atlasName = 'Multilevel Human Atlas'
-const template = 'ICBM 152 2009c Nonlinear Asymmetric'
-
-const pluginName = `fzj.xg.testWidget`
-const pluginDisplayName = `Test Widget Title`
-
-const prepareWidget = ({ template = 'hello world', script = `console.log('hello world')` } = {}) => {
-  
-  return `
-const jsSrc = \`${script.replace(/\`/, '\\`')}\`
-const blob = new Blob([jsSrc], { type: 'text/javascript' })
-window.interactiveViewer.uiHandle.launchNewWidget({
-  name: '${pluginName}',
-  displayName: '${pluginDisplayName}',
-  template: \`${template.replace(/\`/, '\\`')}\`,
-  scriptURL: URL.createObjectURL(blob)
-})`
-}
-
-describe('> plugin api', () => {
-  let iavPage
-
-  beforeEach(async () => {
-    iavPage = new AtlasPage()
-    await iavPage.init()
-    await iavPage.goto()
-    await iavPage.setAtlasSpecifications(atlasName)
-    await iavPage.wait(500)
-    await iavPage.waitUntilAllChunksLoaded()
-  })
-
-  describe('> interactiveViewer', () => {
-    describe('> uiHandle', () => {
-      describe('> launchNewWidget', () => {
-        it('should launch new widget', async () => {
-
-          const prevTitle = await iavPage.execScript(() => window.document.title)
-          await iavPage.execScript(prepareWidget({ script: `window.document.title = 'hello world ' + window.document.title` }))
-
-          await iavPage.wait(500)
-
-          const isDisplayed = await iavPage.widgetPanelIsDispalyed(`Test Widget Title`)
-          expect(isDisplayed).toEqual(true)
-
-          const newTitle = await iavPage.execScript(() => window.document.title)
-          expect(newTitle).toEqual(`hello world ${prevTitle}`)
-        })
-      })
-
-      describe('> cancelPromise', () => {
-        let originalTitle
-        beforeEach(async () => {
-          originalTitle = await iavPage.execScript(() => window.document.title)
-
-          await iavPage.execScript(() => {
-            const pr = interactiveViewer.uiHandle.getUserToSelectARegion('hello world title')
-            pr
-              .then(obj => window.document.title = 'success ' + obj.segment.name)
-              .catch(() => window.document.title = 'failed')
-            window.pr = pr
-          })
-
-          await iavPage.wait(500)
-
-          await iavPage.execScript(() => {
-            const pr = window.pr
-            interactiveViewer.uiHandle.cancelPromise(pr)
-          })
-        })
-
-        it('> cancelPromise rejects promise', async () => {
-          const newTitle = await iavPage.execScript(() => window.document.title)
-          expect(newTitle).toEqual('failed')
-        })
-      })
-
-      describe('> getUserToSelectARegion', () => {
-        let originalTitle
-        const cursorPos = [250, 660]
-        const cursorRegion = 'Area hOc1 (V1, 17, CalcS)'
-        beforeEach(async () => {
-          originalTitle = await iavPage.execScript(() => window.document.title)
-
-          await iavPage.execScript(() => {
-            interactiveViewer.uiHandle.getUserToSelectARegion('hello world title')
-              .then(obj => window.document.title = 'success ' + obj.segment.name)
-              .catch(() => window.document.title = 'failed')
-          })
-          
-          await iavPage.wait(500)
-        })
-
-        it('> shows modal dialog', async () => {
-          const text = await iavPage.getModalText()
-          expect(text).toContain('hello world title')
-        })
-
-        it('> modal has cancel button', async () => {
-          const texts = await iavPage.getModalActions()
-          const idx = texts.findIndex(text => /cancel/i.test(text))
-          expect(idx).toBeGreaterThanOrEqual(0)
-        })
-
-        it('> cancelling by esc rejects pr', async () => {
-          await iavPage.clearAlerts()
-          await iavPage.wait(500)
-          const newTitle = await iavPage.execScript(() => window.document.title)
-          expect(newTitle).toEqual('failed')
-        })
-
-        it('> cancelling by pressing cancel rejects pr', async () => {
-          await iavPage.clickModalBtnByText('Cancel')
-          await iavPage.wait(500)
-          const newTitle = await iavPage.execScript(() => window.document.title)
-          expect(newTitle).toEqual('failed')
-        })
-
-        it('> on clicking region, resolves pr', async () => {
-          await iavPage.cursorMoveToAndClick({ position: cursorPos })
-          await iavPage.wait(500)
-          const newTitle = await iavPage.execScript(() => window.document.title)
-          expect(newTitle).toEqual(`success ${cursorRegion}`)
-        })
-
-        it('> on failusre, clears modal', async () => {
-
-          await iavPage.clearAlerts()
-          await iavPage.wait(500)
-          try {
-            const text = await iavPage.getModalText()
-            fail(`expected modal to clear, but modal has text ${text}`)
-          } catch (e) {
-            expect(true).toEqual(true)
-          }
-        })
-
-        it('> on success, clears modal', async () => {
-
-          await iavPage.cursorMoveToAndClick({ position: cursorPos })
-          await iavPage.wait(500)
-          
-          try {
-            const text = await iavPage.getModalText()
-            fail(`expected modal to clear, but modal has text ${text}`)
-          } catch (e) {
-            expect(true).toEqual(true)
-          }
-        })
-      })
-    })
-  })
-
-  describe('> pluginControl', () => {
-    describe('> onShutdown', () => {
-      it('> works', async () => {
-        const newTitle = `testing pluginControl onShutdown`
-        const script = `window.interactiveViewer.pluginControl['${pluginName}'].onShutdown(() => window.document.title = '${newTitle}')`
-        await iavPage.execScript(prepareWidget({ script }))
-        await iavPage.wait(500)
-        const oldTitle = await iavPage.execScript(() => window.document.title)
-        await iavPage.closeWidgetByname(pluginDisplayName)
-        await iavPage.wait(500)
-        const actualNewTitle = await iavPage.execScript(() => window.document.title)
-        expect(oldTitle).not.toEqual(actualNewTitle)
-        expect(actualNewTitle).toEqual(newTitle)
-      })
-    })
-  })
-})
diff --git a/e2e/src/advanced/urlParsing.prod.e2e-spec.js b/e2e/src/advanced/urlParsing.prod.e2e-spec.js
deleted file mode 100644
index a9a7365cc0e70ab2838e527d431d59164b34a8de..0000000000000000000000000000000000000000
--- a/e2e/src/advanced/urlParsing.prod.e2e-spec.js
+++ /dev/null
@@ -1,145 +0,0 @@
-const { AtlasPage } = require("../util")
-
-describe('> url parsing', () => {
-  let iavPage
-  
-  beforeEach(async () => {
-    iavPage = new AtlasPage()
-    await iavPage.init()
-  })
-
-  it('incorrectly defined templateSelected should clear searchparam', async () => {
-    const searchParam = '/?templateSelected=NoName2&parcellationSelected=NoName'
-    
-    await iavPage.goto(searchParam, { doNotAutomate: true })
-    await iavPage.waitFor(500)
-    const text = await iavPage.getSnackbarMessage()
-    expect(text).toEqual(`Template not found.`)
-  })
-
-  it('> navigation state should be perserved', async () => {
-
-    const searchParam = `/?templateSelected=Big+Brain+%28Histology%29&parcellationSelected=Cytoarchitectonic+Maps&cNavigation=zvyba.z0UJ7._WMxv.-TTch..2_cJ0e.2-OUQG._a9qP._QPHw..7LIx..2CQ3O.1FYC.259Wu..2r6`
-    const expectedNav = {
-      "position": [
-        36806872,
-        325772,
-        34904120
-      ],
-      "orientation": [
-        0.1131771132349968,
-        0.031712327152490616,
-        0.2527998387813568,
-        0.9603527784347534
-      ],
-      "zoom": 11590,
-      "perspectiveZoom": 1922235,
-      "perspectiveOrientation": [
-        -0.2991955280303955,
-        -0.8824243545532227,
-        0.28244855999946594,
-        0.22810545563697815
-      ]
-    }
-
-    await iavPage.goto(searchParam, { doNotAutomate: true })
-    await iavPage.wait(2000)
-    const actualNav = await iavPage.getNavigationState()
-
-    expect(expectedNav.orientation).toEqual(actualNav.orientation)
-    expect(expectedNav.zoom).toEqual(actualNav.zoom)
-
-    // TODO this test fails occassionally
-    // tracking issue: https://github.com/HumanBrainProject/interactive-viewer/issues/464
-    // expect(expectedNav.position).toEqual(actualNav.position)
-    expect(expectedNav.perspectiveOrientation).toEqual(actualNav.perspectiveOrientation)
-    expect(expectedNav.perspectiveZoom).toEqual(actualNav.perspectiveZoom)
-
-  })
-
-  it('> if cRegionSelected is defined, should select region in viewer', async () => {
-    const url = '/?templateSelected=MNI+152+ICBM+2009c+Nonlinear+Asymmetric&parcellationSelected=JuBrain+Cytoarchitectonic+Atlas&cRegionsSelected=%7B"jubrain+mni152+v18+left"%3A"8"%7D'
-    await iavPage.goto(url)
-    await iavPage.clearAlerts()
-
-    const { red, green, blue } = await iavPage.getRgbAt({ position: [600, 490] })
-    expect(red).toBeGreaterThan(0)
-    expect(red).toEqual(green)
-    expect(red).toEqual(blue)
-  })
-
-  it('> [bkwards compat] if ill defined labelIndex for regionsSelected are defined, should handle gracefully', async () => {
-    const url = '/?parcellationSelected=JuBrain+Cytoarchitectonic+Atlas&templateSelected=MNI+Colin+27&navigation=0_0_0_1__-0.2753947079181671_0.6631333827972412_-0.6360703706741333_0.2825356423854828__3000000__-17800000_-6700000_-7500000__200000&regionsSelected=142&niftiLayers=https%3A%2F%2Fneuroglancer.humanbrainproject.org%2Fprecomputed%2FJuBrain%2Fv2.2c%2FPMaps%2FBforebrain_4.nii'
-    await iavPage.goto(url)
-    await iavPage.clearAlerts()
-    await iavPage.wait(5000)
-    await iavPage.waitForAsync()
-    const log = await iavPage.getLog()
-    const filteredLog = log
-      // in headless & non gpu mode, a lot of webgl warnings are thrown
-      .filter(({ level }) => level.toString() === 'SEVERE')
-      .filter(({ message }) => !/Access-Control-Allow-Origin/.test(message))
-
-    // expecting some errors in the console. In catastrophic event, there will most likely be looped errors (on each render cycle)
-    // capture logs and write to spec
-    expect(
-      filteredLog.length
-    ).withContext(
-      JSON.stringify(filteredLog)
-    ).toBeLessThan(
-      50,
-    )
-  })
-
-  it('> if niftiLayers are defined, parcellation layer should be hidden', async () => {
-    const url = `/?parcellationSelected=JuBrain+Cytoarchitectonic+Atlas&templateSelected=MNI+Colin+27&cNavigation=0.0.0.-W000.._NjRq.2-Klk_._-Hmu.2_BdKx..DMVW..1vjMG.4eIG8~.hqT5~..10vB&regionsSelected=142&niftiLayers=https%3A%2F%2Fneuroglancer.humanbrainproject.org%2Fprecomputed%2FJuBrain%2Fv2.2c%2FPMaps%2FBforebrain_4.nii`
-    await iavPage.goto(url)
-    await iavPage.clearAlerts()
-
-    const { red, green, blue } = await iavPage.getRgbAt({ position: [600, 490] })
-    
-    expect(red).toBeGreaterThan(0)
-    expect(red).toEqual(green)
-    expect(red).toEqual(blue)
-  })
-
-  it('> if using niftilayers should show deprecation worning')
-
-  it('> pluginStates should be fetched even if no template or parc are selected', async () => {
-
-    const searchParam = new URLSearchParams()
-    searchParam.set('pluginStates', 'http://localhost:3001/manifest.json')
-    await iavPage.goto(`/?${searchParam.toString()}`, { interceptHttp: true, doNotAutomate: true })
-    await iavPage.wait(10000)
-    const interceptedCalls = await iavPage.getInterceptedHttpCalls()
-    expect(
-      interceptedCalls
-    ).toContain(jasmine.objectContaining(
-      {
-        method: 'GET',
-        url: 'http://localhost:3001/manifest.json'
-      }
-    ))
-  })
-
-  it('> pluginStates should result in xhr to get pluginManifest', async () => {
-
-    const searchParam = new URLSearchParams()
-    searchParam.set('templateSelected', 'MNI 152 ICBM 2009c Nonlinear Asymmetric')
-    searchParam.set('parcellationSelected', 'JuBrain Cytoarchitectonic Atlas')
-    searchParam.set('pluginStates', 'http://localhost:3001/manifest.json')
-
-    await iavPage.goto(`/?${searchParam.toString()}`, { interceptHttp: true, doNotAutomate: true })
-    await iavPage.wait(10000)
-    const interceptedCalls = await iavPage.getInterceptedHttpCalls()
-    expect(
-      interceptedCalls
-    ).toContain(jasmine.objectContaining(
-      {
-        method: 'GET',
-        url: 'http://localhost:3001/manifest.json'
-      }
-    ))
-  })
-
-})
diff --git a/e2e/src/layout/atlasWidgetBtns.prod.e2e-spec.js b/e2e/src/layout/atlasWidgetBtns.prod.e2e-spec.js
deleted file mode 100644
index a9936493c68400e87288e5ed8eace99dcf69c74c..0000000000000000000000000000000000000000
--- a/e2e/src/layout/atlasWidgetBtns.prod.e2e-spec.js
+++ /dev/null
@@ -1,40 +0,0 @@
-/**
- * TODO finish tests!
- */
-
-describe('> atlas widget btns', () => {
-  it('> fails unless tests are written', () => {
-    expect(true).toEqual(false)
-  })
-  describe('> when default layer is selected', () => {
-    it('> hierarchy btn should show hierarchy', () => {
-
-    })
-
-    it('> connectivity btn should show connectivity', () => {
-
-    })
-
-    it('> dataset should show dataset', () => {
-
-    })
-  })
-
-  describe('> when another layer is displayed', () => {
-    it('> mat-chip should update', () => {
-
-    })
-
-    it('> cicking close on mat chip should result in removing additional layer', () => {
-
-    })
-
-    it('> hierarchy should be updated', () => {
-
-    })
-
-    it('> databrowser should be updated', () => {
-      
-    })
-  })
-})
\ No newline at end of file
diff --git a/e2e/src/layout/home.prod.e2e-spec.js b/e2e/src/layout/home.prod.e2e-spec.js
deleted file mode 100644
index 0ef5abf53e2514e935dca67b9e3798cd5fca04aa..0000000000000000000000000000000000000000
--- a/e2e/src/layout/home.prod.e2e-spec.js
+++ /dev/null
@@ -1,30 +0,0 @@
-const { BasePage } = require('../util')
-
-describe('> home.prod.e2e-spec.js', () => {
-  describe('> home page', () => {
-    it('> should load home page', async () => {
-      const newPage = new BasePage()
-      await newPage.init()
-      await newPage.goto()
-      const cards = await newPage.areVisible(`mat-card`)
-      /**
-       * expecting 3 atlases
-       */
-      expect(cards.length).toEqual(3)
-    })
-  })
-
-  describe('> quickstart', () => {
-    it('> should load quickstart page', async () => {
-
-      const newPage = new BasePage()
-      await newPage.init()
-      await newPage.goto(`/quickstart`)
-      const table = await newPage.areVisible(`table`)
-      /**
-       * expecting at least 1 table
-       */
-      expect(table.length).toBeGreaterThan(0)
-    })
-  })
-})
diff --git a/e2e/src/layout/layout.prod.e2e-spec.js b/e2e/src/layout/layout.prod.e2e-spec.js
deleted file mode 100644
index e3fcfde8465be3e1cf1251d2e72d414cd2a8b831..0000000000000000000000000000000000000000
--- a/e2e/src/layout/layout.prod.e2e-spec.js
+++ /dev/null
@@ -1,108 +0,0 @@
-const { AtlasPage } = require('../util')
-
-const MAT_SIDENAV_TIMEOUT = 500
-
-describe('> sidenav', () => {
-  let atlasPage
-
-  beforeEach(async () => {
-    atlasPage = new AtlasPage()
-    await atlasPage.init()
-    await atlasPage.goto('/?templateSelected=MNI+152+ICBM+2009c+Nonlinear+Asymmetric&parcellationSelected=JuBrain+Cytoarchitectonic+Atlas')
-    await atlasPage.wait(MAT_SIDENAV_TIMEOUT)
-    await atlasPage.dismissModal()
-
-    do {
-
-    } while(
-      await atlasPage.wait(100),
-      !(await atlasPage.viewerIsPopulated())
-    )
-  })
-
-  it('> on init, side panel should be visible', async () => {
-    const sideNavIsDisplayed = await atlasPage.sideNavIsVisible()
-    expect(sideNavIsDisplayed).toEqual(true)
-
-    const toggleTabIsDIsplayed = await atlasPage.sideNavTabIsVisible()
-    expect(toggleTabIsDIsplayed).toEqual(true)
-  })
-
-  describe('> toggling', () => {
-    it('> toggle tab should toggle side nav', async () => {
-      const init = await atlasPage.sideNavIsVisible()
-      expect(init).toEqual(true)
-
-      await atlasPage.clickSideNavTab()
-      await atlasPage.wait(MAT_SIDENAV_TIMEOUT)
-      const expectHidden = await atlasPage.sideNavIsVisible()
-      expect(expectHidden).toEqual(false)
-
-      await atlasPage.clickSideNavTab()
-      await atlasPage.wait(MAT_SIDENAV_TIMEOUT)
-      const expectShown = await atlasPage.sideNavIsVisible()
-      expect(expectShown).toEqual(true)
-    })
-  })
-})
-
-describe('> status panel', () => {
-
-  let atlasPage
-
-  beforeEach(async () => {
-    atlasPage = new AtlasPage()
-    await atlasPage.init()
-    await atlasPage.goto('/?templateSelected=MNI+152+ICBM+2009c+Nonlinear+Asymmetric&parcellationSelected=JuBrain+Cytoarchitectonic+Atlas')
-    await atlasPage.wait(MAT_SIDENAV_TIMEOUT)
-    await atlasPage.dismissModal()
-
-    do {
-
-    } while(
-      await atlasPage.wait(100),
-      !(await atlasPage.viewerIsPopulated())
-    )
-  })
-
-  afterEach(() => {
-    atlasPage = null
-  })
-
-  it('> on init, status panel should not be visible', async () => {
-    
-    const init = await atlasPage.statusPanelIsVisible()
-    expect(init).toEqual(false)
-  })
-
-  it('> on toggling side panel, status panel should become visible', async () => {
-    await atlasPage.clickSideNavTab()
-    await atlasPage.wait(MAT_SIDENAV_TIMEOUT)
-
-    const expectVisible = await atlasPage.statusPanelIsVisible()
-    expect(expectVisible).toEqual(true)
-  })
-
-  it('> on click status panel, side nav become visible, status panel become invisible', async () => {
-
-    await atlasPage.clickSideNavTab()
-    await atlasPage.wait(MAT_SIDENAV_TIMEOUT)
-  
-    await atlasPage.clickStatusPanel()
-    await atlasPage.wait(MAT_SIDENAV_TIMEOUT)
-
-    const expectHidden = await atlasPage.statusPanelIsVisible()
-    expect(expectHidden).toEqual(false) 
-    
-    const expectVisible = await atlasPage.sideNavIsVisible()
-    expect(expectVisible).toEqual(true)
-  })
-})
-
-describe('> double mat drawer', () => {
-  describe('> on user interaction', () => {
-    describe('> when user closes region chip', () => {
-      it('> mat drawers should remain closed')
-    })
-  })
-})
diff --git a/e2e/src/layout/pluginInfo.e2e-spec.js b/e2e/src/layout/pluginInfo.e2e-spec.js
deleted file mode 100644
index 50bc4e83a8fed67fc087ef06559a2112474447c5..0000000000000000000000000000000000000000
--- a/e2e/src/layout/pluginInfo.e2e-spec.js
+++ /dev/null
@@ -1,35 +0,0 @@
-const { LayoutPage } = require("../util")
-
-describe('> plugin dropdown', () => {
-  let layoutPage
-
-  beforeEach(async () => {
-    layoutPage = new LayoutPage()
-    await layoutPage.init()
-    await layoutPage.goto()
-    await layoutPage.dismissModal()
-  })
-
-  it('> click on drop down btn shows drop down menu', async () => {
-    await layoutPage.showToolsMenu()
-    await layoutPage.wait(500)
-    const tools = await layoutPage.getVisibleTools()
-    expect(tools.length).toBeGreaterThan(0)
-  })
-
-  it('> click on info btn shows info', async () => {
-    await layoutPage.showToolsMenu()
-    await layoutPage.wait(500)
-    const tools = await layoutPage.getVisibleTools()
-    const exampleIndex = tools.findIndex(tool => /Example\ Plugin/.test(tool))
-    expect(exampleIndex).toBeGreaterThanOrEqual(0)
-    await layoutPage.clickOnNthTool(exampleIndex, '[aria-label="About this plugin"]')
-    await layoutPage.wait(500)
-    const txt = await layoutPage.getModalText()
-    expect(txt).toContain('About Example Plugin (v0.0.1)')
-    expect(txt).toContain('description of example plugin')
-    expect(txt).toContain('http://HOSTNAME/home.html')
-    expect(txt).toContain('Xiaoyun Gui <x.gui@fz-juelich.de>')
-    
-  })
-})
diff --git a/e2e/src/layout/scrollDatasetContainer.prod.e2e-spec.js b/e2e/src/layout/scrollDatasetContainer.prod.e2e-spec.js
deleted file mode 100644
index 97c457c1c34d849f36269c631c283d532616d42e..0000000000000000000000000000000000000000
--- a/e2e/src/layout/scrollDatasetContainer.prod.e2e-spec.js
+++ /dev/null
@@ -1,36 +0,0 @@
-const { AtlasPage } = require('../util')
-const { ARIA_LABELS } = require('../../../common/constants')
-describe('> scroll dataset container', () => {
-  let iavPage
-
-  beforeEach(async () => {
-    iavPage = new AtlasPage()
-    await iavPage.init()
-
-  })
-
-  it('> can scroll to the end', async () => {
-    await iavPage.goto()
-    await iavPage.selectTitleCard('ICBM 2009c Nonlinear Asymmetric')
-    await iavPage.wait(1000)
-    await iavPage.waitForAsync()
-
-    await iavPage.click(`[aria-label="${ARIA_LABELS.TOGGLE_EXPLORE_PANEL}"]`)
-
-    await iavPage.clearAlerts()
-
-    let countdown = 100
-    do {
-      await iavPage.scrollElementBy(`[aria-label="${ARIA_LABELS.LIST_OF_DATASETS}"]`, {
-        delta: [0, 100]
-      })
-      await iavPage.wait(100)
-      countdown --
-    }while(countdown > 0)
-
-    await iavPage.wait(500)
-
-    const val = await iavPage.getScrollStatus(`[aria-label="${ARIA_LABELS.LIST_OF_DATASETS}"]`)
-    expect(val).toBeGreaterThanOrEqual(9900)
-  })
-})
\ No newline at end of file
diff --git a/e2e/src/layout/statusbar.prod.e2e-spec.js b/e2e/src/layout/statusbar.prod.e2e-spec.js
deleted file mode 100644
index facf6b01c61327e12946de0f04fdc67f6a43eb72..0000000000000000000000000000000000000000
--- a/e2e/src/layout/statusbar.prod.e2e-spec.js
+++ /dev/null
@@ -1,75 +0,0 @@
-const { AtlasPage } = require('../util')
-const { ARIA_LABELS } = require('../../../common/constants')
-const { retry } = require('../../../common/util')
-describe('> statusbar', () => {
-  let atlasPage = new AtlasPage()
-  beforeEach(async () => {
-    atlasPage = new AtlasPage()
-    await atlasPage.init()
-  })
-
-  it('> on init, should not be visible', async () => {
-    await atlasPage.goto()
-    try {
-      const visible = await atlasPage.isVisible(`[aria-label="${ARIA_LABELS.STATUS_PANEL}"]`)
-      expect(visible).toBeFalsy()
-    } catch (e) {
-
-    }
-  })
-
-  describe('> on template selection', () => {
-    beforeEach(async () => {
-      await atlasPage.goto()
-      await atlasPage.selectTitleCard('MNI Colin 27')
-      await retry(async () => {
-        const populated = await atlasPage.viewerIsPopulated()
-        if (!populated) throw new Error(`viewer not yet populated`)
-      }, { retries: 10, timeout: 500 })
-  
-    })
-    it('> on template selection, should be visible', async () => {
-  
-      const visible = await atlasPage.isVisible(`[aria-label="${ARIA_LABELS.STATUS_PANEL}"]`)
-      expect(visible).toBeTruthy()
-    })
-  
-    it('> on template selection, minimised status panel should be visible', async () => {
-      const maximaizeVisible = await atlasPage.isVisible(`[aria-label="${ARIA_LABELS.SHOW_FULL_STATUS_PANEL}"]`)
-      expect(maximaizeVisible).toBeTruthy()
-      try {
-        const minimizeVisible = await atlasPage.isVisible(`[aria-label="${ARIA_LABELS.HIDE_FULL_STATUS_PANEL}"]`)
-        expect(minimizeVisible).toBeFalsy()
-      } catch (e) {
-
-      }
-    })
-
-    it('> clicking maximise btn should maximise the status panel', async () => {
-      await atlasPage.click(`[aria-label="${ARIA_LABELS.SHOW_FULL_STATUS_PANEL}"]`)
-      await atlasPage.wait(500)
-      const minimizeVisible = await atlasPage.isVisible(`[aria-label="${ARIA_LABELS.HIDE_FULL_STATUS_PANEL}"]`)
-      expect(minimizeVisible).toBeTruthy()
-      try {
-        const maxVisible = await atlasPage.isVisible(`[aria-label="${ARIA_LABELS.SHOW_FULL_STATUS_PANEL}"]`)
-        expect(maxVisible).toBeFalsy()
-      } catch (e) {
-
-      }
-    })
-
-    it('> click min btn should minimize', async () => {
-      await atlasPage.click(`[aria-label="${ARIA_LABELS.SHOW_FULL_STATUS_PANEL}"]`)
-      await atlasPage.wait(500)
-      await atlasPage.click(`[aria-label="${ARIA_LABELS.HIDE_FULL_STATUS_PANEL}"]`)
-      await atlasPage.wait(500)
-      try {
-        const minimizeVisible = await atlasPage.isVisible(`[aria-label="${ARIA_LABELS.HIDE_FULL_STATUS_PANEL}"]`)
-        expect(minimizeVisible).toBeFalsy()
-      } catch (e) {
-
-      }
-    })
-  })
-
-})
\ No newline at end of file
diff --git a/e2e/src/layout/viewerCtxMenu.prod.e2e-spec.js b/e2e/src/layout/viewerCtxMenu.prod.e2e-spec.js
deleted file mode 100644
index 78ffbd9410cd826e6bc9ba846f2a59a56248ea6c..0000000000000000000000000000000000000000
--- a/e2e/src/layout/viewerCtxMenu.prod.e2e-spec.js
+++ /dev/null
@@ -1,94 +0,0 @@
-const { AtlasPage } = require('../util')
-const { ARIA_LABELS } = require('../../../common/constants')
-const dict = {
-  "ICBM 2009c Nonlinear Asymmetric": {
-    "JuBrain Cytoarchitectonic Atlas": {
-      tests:[
-        {
-          position: [550, 270],
-          expectedLabelName: 'Fastigial Nucleus (Cerebellum) - right hemisphere',
-        }
-      ]
-    }
-  },
-  "Big Brain (Histology)": {
-    "Cytoarchitectonic Maps": {
-      tests:[
-        {
-          position: [440,200],
-          expectedLabelName: 'Area hOc1 (V1, 17, CalcS)',
-          expectedLabelStatus: '(fully mapped)'
-        }
-      ]
-    }
-  }
-}
-
-describe('> viewerCtxMenu', () => {
-
-  for (const templateName in dict) {
-    for (const parcellationName in dict[templateName]) {
-      describe(`> on ${templateName} / ${parcellationName}`, () => {
-        beforeAll(async () => {
-          iavPage = new AtlasPage()
-          await iavPage.init()
-          await iavPage.goto()
-          await iavPage.selectTitleTemplateParcellation(templateName, parcellationName)
-          await iavPage.wait(500)
-          await iavPage.waitForAsync()
-        })
-
-        it('> does not appear on init', async () => {
-          const visible = await iavPage.isVisible(`[aria-label="${ARIA_LABELS.CONTEXT_MENU}"]`)
-          expect(visible).toBeFalse()
-        })
-  
-        it('> appears on click', async () => {
-          const { tests } = dict[templateName][parcellationName]
-          const { position } = tests[0]
-          await iavPage.cursorMoveToAndClick({ position })
-          await iavPage.wait(500)
-          const visible = await iavPage.isVisible(`[aria-label="${ARIA_LABELS.CONTEXT_MENU}"]`)
-          expect(visible).toBeTrue()
-        })
-
-        it('> Title includes region status', async () => {
-          const { tests } = dict[templateName][parcellationName]
-          const { expectedLabelStatus, expectedLabelName } = tests[0]
-          await iavPage.wait(500)
-          if (expectedLabelStatus) {
-            const fullMenuText = await iavPage.getText(`[aria-label="${ARIA_LABELS.CONTEXT_MENU}"]`)
-            expect(fullMenuText.includes(`${expectedLabelName} ${expectedLabelStatus}`)).toEqual(true)
-          }
-        })
-
-        it('> Title do not includes region status', async () => {
-          const { tests } = dict[templateName][parcellationName]
-          const { expectedLabelStatus, expectedLabelName } = tests[0]
-          await iavPage.wait(500)
-          if (!expectedLabelStatus) {
-            const fullMenuText = await iavPage.getText(`[aria-label="${ARIA_LABELS.CONTEXT_MENU}"]`)
-            expect(fullMenuText.includes(expectedLabelName)).toEqual(true)
-          }
-        })
-
-        it('> pos does not change when click inside', async () => {
-          const { x: xBefore, y: yBefore, height: hBefore } = await iavPage.isAt(`[aria-label="${ARIA_LABELS.CONTEXT_MENU}"]`)
-          await iavPage.click(`[aria-label="${ARIA_LABELS.SHOW_IN_OTHER_REF_SPACE}"]`)
-          await iavPage.wait(500)
-          const { x: xAfter, y: yAfter, height: hAfter } = await iavPage.isAt(`[aria-label="${ARIA_LABELS.CONTEXT_MENU}"]`)
-          expect(xBefore).toEqual(xAfter)
-          expect(yBefore).toEqual(yAfter)
-          expect(hAfter).toBeGreaterThan(hBefore)
-        })
-
-        it('> disappear again on click of anywhere else', async () => {
-          await iavPage.cursorMoveToAndClick({ position: [10, 10] })
-          await iavPage.wait(500)
-          const visible = await iavPage.isVisible(`[aria-label="${ARIA_LABELS.CONTEXT_MENU}"]`)
-          expect(visible).toBeFalse()
-        })
-      })
-    }
-  }
-})
diff --git a/e2e/src/material-util.js b/e2e/src/material-util.js
deleted file mode 100644
index 04f9c994fac5310b6d1c50ab915ec3f1ddcc215f..0000000000000000000000000000000000000000
--- a/e2e/src/material-util.js
+++ /dev/null
@@ -1,19 +0,0 @@
-const { By } = require('selenium-webdriver')
-
-async function polyFillClick(cssSelector){
-  if (!cssSelector) throw new Error(`click method needs to define a css selector`)
-  const webEl = this._browser.findElement( By.css(cssSelector) )
-  try {
-    await webEl.click()
-  } catch (e) {
-    const id = await webEl.getAttribute('id')
-    const newId = id.replace(/-input$/, '')
-    await this._browser.findElement(
-      By.id(newId)
-    ).click()
-  }
-}
-
-module.exports = {
-  polyFillClick
-}
diff --git a/e2e/src/navigating/btnZoomInOut.prod.e2e-spec.js b/e2e/src/navigating/btnZoomInOut.prod.e2e-spec.js
deleted file mode 100644
index d8349964da698991f33631ca33365f6b4f0fbacb..0000000000000000000000000000000000000000
--- a/e2e/src/navigating/btnZoomInOut.prod.e2e-spec.js
+++ /dev/null
@@ -1,138 +0,0 @@
-const { AtlasPage } = require('../util')
-const { width, height } = require('../../opts')
-const { ARIA_LABELS } = require('../../../common/constants')
-
-describe('> zoom in btns on panels', () => {
-  
-  let iavPage
-  const url = '/?templateSelected=MNI+152+ICBM+2009c+Nonlinear+Asymmetric&parcellationSelected=JuBrain+Cytoarchitectonic+Atlas'
-
-  describe('> on hover overlay elements', () => {
-    beforeEach(async () => {
-      iavPage = new AtlasPage()
-      await iavPage.init()
-      await iavPage.goto(url)
-    })
-    it('> panel btns do not show', async () => {
-      
-      await iavPage.cursorMoveToElement(`[aria-label="${ARIA_LABELS.SELECT_ATLAS}"]`)
-
-      await iavPage.wait(500)
-
-      const visibleFlags = await iavPage.areVisible(`[aria-label="${ARIA_LABELS.ZOOM_IN}"]`)
-      expect(visibleFlags.length).toBe(4)
-      expect(visibleFlags).toEqual([false, false, false, false])
-    })
-  })
-
-  const delta = 30
-  const arr = [
-    [ width / 2 - delta, height / 2 - delta ],
-    [ width / 2 + delta, height / 2 - delta ],
-    [ width / 2 - delta, height / 2 + delta ],
-    [ width / 2 + delta, height / 2 + delta ],
-  ]
-
-  for (const key of [ ARIA_LABELS.ZOOM_IN, ARIA_LABELS.ZOOM_OUT ]) {
-    describe(`> testing ${key}`, () => {
-
-      for (const idx in arr) {
-        describe(`> panel ${idx}`, () => {
-          beforeAll(async () => {
-            iavPage = new AtlasPage()
-            await iavPage.init()
-            await iavPage.goto(url)
-          })
-          it('> mouse over should show zoom btns', async () => {
-            
-            await iavPage.cursorMoveTo({
-              position: arr[idx]
-            })
-    
-            await iavPage.wait(500)
-            const visibleFlags = await iavPage.areVisible(`[aria-label="${key}"]`)
-            expect(visibleFlags.length).toBe(4)
-    
-            const expectedFlags = [false, false, false, false]
-            expectedFlags[idx] = true
-            expect(visibleFlags).toEqual(expectedFlags)
-          })
-    
-    
-          describe(`> "${key}" btns btn works`, () => {
-            let o, po, pz, z, p,
-            no2, npo2, npz2, nz2, np2
-            beforeAll(async () => {
-    
-              const navState = await iavPage.getNavigationState()
-    
-              o = navState.orientation
-              po = navState.perspectiveOrientation
-              pz = navState.perspectiveZoom
-              z = navState.zoom
-              p = navState.position
-    
-              const arrOut = await iavPage.areAt(`[aria-label="${key}"]`)
-    
-              const positionOut = [
-                arrOut[idx].x + arrOut[idx].width / 2,
-                arrOut[idx].y + arrOut[idx].height / 2
-              ]
-              await iavPage.cursorMoveToAndClick({
-                position: positionOut
-              })
-              await iavPage.wait(2000)
-              const newNavState2 = await iavPage.getNavigationState()
-              no2 = newNavState2.orientation
-              npo2 = newNavState2.perspectiveOrientation
-              npz2 = newNavState2.perspectiveZoom
-              nz2 = newNavState2.zoom
-              np2 = newNavState2.position
-    
-            })
-    
-            it('> expect orientation to be unchanged', () => {
-              expect(o).toEqual(no2)
-            })
-    
-            it('> expects perspective orientation to be unchanged', () => {
-              expect(po).toEqual(npo2)
-            })
-    
-            it('> expect position to be unchanged', () => {
-              expect(p).toEqual(np2)
-            })
-    
-            /**
-             * when iterating over array accessor, the key are actually string
-             */
-            if (Number(idx) === 3) {
-              it('> expects zoom to be unchanged', () => {
-                expect(z).toEqual(nz2)
-              })
-              it('> expects perspectivezoom to increase with zoom out btn', () => {
-                if (key === ARIA_LABELS.ZOOM_OUT) {
-                  expect(pz).toBeLessThan(npz2)
-                } else {
-                  expect(pz).toBeGreaterThan(npz2)
-                }
-              })
-            } else {
-              it('> expects perspective zoom to be unchanged', () => {
-                expect(pz).toEqual(npz2)
-              })
-    
-              it('> expect zoom to  increase with zoom out btn', () => {
-                if (key === ARIA_LABELS.ZOOM_OUT) {
-                  expect(z).toBeLessThan(nz2)
-                } else {
-                  expect(z).toBeGreaterThan(nz2)
-                }
-              })
-            }
-          })
-        })
-      }
-    })
-  }
-})
diff --git a/e2e/src/navigating/changeTemplate.prod.e2e-spec.js b/e2e/src/navigating/changeTemplate.prod.e2e-spec.js
deleted file mode 100644
index df74a6cbdc3326ff0640abe1e7ae9d8d49998fff..0000000000000000000000000000000000000000
--- a/e2e/src/navigating/changeTemplate.prod.e2e-spec.js
+++ /dev/null
@@ -1,65 +0,0 @@
-const { AtlasPage } = require('../util')
-
-describe('trans template navigation', () => {
-  let iavPage
-  
-  beforeEach(async () => {
-    iavPage = new AtlasPage()
-    await iavPage.init()
-    
-  })
-
-  it('when user moves from template a -> template b, a xhr call is made', async () => {
-
-    const searchParam = new URLSearchParams()
-    searchParam.set('templateSelected', 'MNI 152 ICBM 2009c Nonlinear Asymmetric')
-    searchParam.set('parcellationSelected', 'JuBrain Cytoarchitectonic Atlas')
-    await iavPage.goto(`/?${searchParam.toString()}`, { interceptHttp: true, doNotAutomate: true })
-    await iavPage.wait(200)
-    await iavPage.dismissModal()
-
-    await iavPage.waitUntilAllChunksLoaded()
-
-    await iavPage.selectDropdownTemplate('Big Brain (Histology)')
-    await iavPage.wait(2000)
-    const interceptedCalls = await iavPage.getInterceptedHttpCalls()
-    
-    expect(interceptedCalls).toBeTruthy()
-
-    const found = interceptedCalls && interceptedCalls.find(({ method, url }) => {
-      return method === 'POST' && /transform-points/.test(url)
-    })
-    expect(!!found).toBe(true)
-  })
-
-  it('Check region color after template change when region was selected', async () => {
-
-    const url = '/?templateSelected=MNI+152+ICBM+2009c+Nonlinear+Asymmetric&parcellationSelected=JuBrain+Cytoarchitectonic+Atlas'
-    const area = 'Area TE 3 (STG) - right hemisphere'
-    const expectedPosition = [630, 510]
-    const expectedColor = {red: 70, green: 139, blue: 57}
-
-    await iavPage.goto(url)
-
-    await iavPage.searchRegionWithText(area)
-    await iavPage.wait(1000)
-
-    await iavPage.selectSearchRegionAutocompleteWithText()
-    await iavPage.dismissModal()
-    await iavPage.wait(500)
-    await iavPage.selectDropdownTemplate('MNI Colin 27')
-    /**
-     * wait for template translate & js execution
-     */
-    await iavPage.wait(1000)
-    await iavPage.waitUntilAllChunksLoaded()
-    const actualColor = await iavPage.getRgbAt({ position: expectedPosition })
-
-    for (const key in actualColor) {
-      expect(Math.abs(actualColor[key] - expectedColor[key])).toBeLessThan(5)
-    }
-
-  })
-
-  // TODO test that nav/zoom/orientation are actually preserved
-})
diff --git a/e2e/src/navigating/loadingOrder.prod.e2e-spec.js b/e2e/src/navigating/loadingOrder.prod.e2e-spec.js
deleted file mode 100644
index dc62278d79d3ef39bf926952d4f8eec73e0a30cb..0000000000000000000000000000000000000000
--- a/e2e/src/navigating/loadingOrder.prod.e2e-spec.js
+++ /dev/null
@@ -1,120 +0,0 @@
-const { AtlasPage } = require('../util')
-const { IDS } = require('../../../common/constants')
-const { width, height } = require('../../opts')
-const { hrtime } = process
-
-const templates = [
-  ["Big Brain (Histology)", "Cytoarchitectonic Maps"],
-  ["Waxholm Space rat brain MRI/DTI", "Waxholm Space rat brain atlas v3"]
-]
-
-describe('> when loading an atlas', () => {
-  let iavPage = new AtlasPage()
-
-  const getNumOfSpinners = async () => {
-
-    try {
-      return await iavPage.execScript(`
-        const els = document.querySelectorAll('.spinnerAnimationCircle')
-        return els && els.length
-        `)
-    } catch (e) {
-      return false
-    }
-  }
-
-  const checkRoleStatus = async () => {
-    try {
-      const text = await iavPage.execScript(`
-        const el = document.getElementById('${IDS.MESH_LOADING_STATUS}')
-        return el && el.textContent
-        `)
-      return text && /Loading\s.*?chunks/.test(text)
-    } catch (e) {
-      return false
-    }
-  }
-
-  beforeEach(async () => {
-    iavPage = new AtlasPage()
-    await iavPage.init()
-    await iavPage.goto()
-  })
-
-  for (const [template, parcelation] of templates) {
-
-    const masterTimer = {moving: null, nonmoving: null}
-
-    it(`> for ${template}, image will be loaded first`, async () => {
-      const timer = hrtime()
-      await iavPage.selectTitleTemplateParcellation(template, parcelation)
-      await iavPage.wait(500)
-      const preSpinners = await getNumOfSpinners()
-      expect(preSpinners).toBe(4)
-      while( await checkRoleStatus() ) {
-        await iavPage.wait(200)
-      }
-
-      const finishedTimer = hrtime(timer)
-
-      const postSpinners = await getNumOfSpinners()
-      /**
-       * There is currently a known bug that spinner in IDS.MESH_LOADING_STATUS is hidden with opacity 0 rather than unload from DOM
-       * TODO fix bug
-       */
-      expect(postSpinners).toBeLessThanOrEqual(2)
-      expect(postSpinners).toBeGreaterThanOrEqual(1)
-      
-      const sec = finishedTimer[0] + finishedTimer[1] / 1e9
-      masterTimer.nonmoving = sec
-    })
-
-    it('> if user was panning, it should take longer as loading takes priority', async () => {
-      const timer = hrtime()
-      await iavPage.selectTitleTemplateParcellation(template, parcelation)
-      await iavPage.wait(500)
-      
-      await iavPage.cursorMoveToAndDrag({
-        position: [ Math.round(width / 4 * 3), Math.round(height / 4) ],
-        delta: [ Math.round(width / 8), Math.round(height / 8)]
-      })
-
-      await iavPage.wait(500)
-
-      await iavPage.cursorMoveToAndDrag({
-        position: [ Math.round(width / 4 * 3), Math.round(height / 4) ],
-        delta: [ 1, Math.round(height / -4)]
-      })
-
-      while( await checkRoleStatus() ) {
-        await iavPage.wait(200)
-      }
-
-      const finishedTimer = hrtime(timer)
-      
-      const sec = finishedTimer[0] + finishedTimer[1] / 1e9
-      masterTimer.moving = sec
-
-      expect(masterTimer.moving).toBeGreaterThan(masterTimer.nonmoving)
-    })
-
-    it('> if the meshes are already loading, do not show overlay', async () => {
-      
-      await iavPage.selectTitleTemplateParcellation(template, parcelation)
-      await iavPage.wait(500)
-      
-      while( await checkRoleStatus() ) {
-        await iavPage.wait(200)
-      }
-
-      await iavPage.cursorMoveToAndDrag({
-        position: [ Math.round(width / 4 * 3), Math.round(height / 4) ],
-        delta: [ Math.round(width / 8), Math.round(height / 8)]
-      })
-
-      const roleStatus = await checkRoleStatus()
-
-      expect(roleStatus).toBeFalsy()
-    })
-  }
-})
diff --git a/e2e/src/navigating/mouseOverNehuba.prod.e2e-spec.js b/e2e/src/navigating/mouseOverNehuba.prod.e2e-spec.js
deleted file mode 100644
index d446ea1ed137df9132c2b1a62ecc1781c0e42df8..0000000000000000000000000000000000000000
--- a/e2e/src/navigating/mouseOverNehuba.prod.e2e-spec.js
+++ /dev/null
@@ -1,193 +0,0 @@
-const { AtlasPage } = require('../util')
-
-const dictionary = {
-  "Allen Mouse Common Coordinate Framework v3": {
-    "Allen Mouse Common Coordinate Framework v3 2017": {
-      tests: [
-        {
-          position: [530, 530],
-          expectedLabelName: 'Primary somatosensory area, barrel field, layer 4',
-        },
-        {
-          position: [590, 120],
-          expectedLabelName: 'Retrosplenial area, ventral part, layer 2/3',
-        }
-      ]
-    },
-    "Allen Mouse Common Coordinate Framework v3 2015": {
-      tests: [
-        {
-          position: [520, 530],
-          expectedLabelName: 'Primary somatosensory area, barrel field',
-        },
-        {
-          position: [588, 115],
-          expectedLabelName: 'Retrosplenial area, ventral part',
-        }
-      ]
-    }
-  },
-  "Waxholm Space rat brain MRI/DTI": {
-    "Waxholm Space rat brain atlas v3": {
-      tests: [
-        {
-          position: [350, 170],
-          expectedLabelName: 'neocortex',
-        },
-        {
-          position: [320, 560],
-          expectedLabelName: 'corpus callosum and associated subcortical white matter',
-        }
-      ]
-    },
-    "Waxholm Space rat brain atlas v2": {
-      tests: [
-        {
-          position: [500, 630],
-          expectedLabelName: 'lateral entorhinal cortex',
-        },
-        {
-          position: [300, 200],
-          expectedLabelName: 'dentate gyrus',
-        }
-      ]
-    },
-    "Waxholm Space rat brain atlas v1": {
-      tests: [
-        {
-          position: [480, 680],
-          expectedLabelName: 'inner ear',
-        },
-        {
-          position: [550, 550],
-          expectedLabelName: 'corpus callosum and associated subcortical white matter',
-        }
-      ]
-    }
-  },
-  "ICBM 2009c Nonlinear Asymmetric": {
-    "JuBrain Cytoarchitectonic Atlas": {
-      tests:[
-        {
-          position: [550, 270],
-          expectedLabelName: 'Fastigial Nucleus (Cerebellum) - right hemisphere',
-        },
-        {
-          position: [600, 490],
-          expectedLabelName: 'Area 6ma (preSMA, mesial SFG) - left hemisphere',
-        }
-      ]
-    },
-    "Fibre Bundle Atlas - Long Bundle": {
-      tests: [
-        {
-          position: [300, 210],
-          expectedLabelName: 'InferiorFrontoOccipital - Right',
-        },
-        {
-          position: [680, 590],
-          expectedLabelName: 'InferiorLongitudinal - Left',
-        }
-      ]
-    },
-    "Fibre Bundle Atlas - Short Bundle": {
-      tests: [
-        {
-          position: [300, 100],
-          expectedLabelName: 'rh_SP-SM_0',
-        },
-        {
-          /**
-           * Changed from [677, 579] as it is extremely unfortunate in that
-           * it is literally the connecting point between lh_CAC-PrCu_0 and lh_PoCi-PrCu_0
-           */
-          position: [677, 579],
-          expectedLabelName: 'lh_ST-TT_0',
-        }
-      ]
-    }
-  },
-  // TODO big brain cytomap occassionally resets center position to -20mm. investigate why
-  "Big Brain (Histology)": {
-    "Cytoarchitectonic Maps": {
-      url: "/?templateSelected=Big+Brain+%28Histology%29&parcellationSelected=Cytoarchitectonic+Maps&cNavigation=0.0.0.-W000.._eCwg.2-FUe3._-s_W.2_evlu..7LIx..1n5q~.1FYC.2Is-..1B9C",
-      tests: [
-        {
-          position: [686, 677],
-          expectedLabelName: 'Area STS1 (STS)'
-        },
-        {
-          position: [617,682],
-          expectedLabelName: 'Entorhinal Cortex'
-        }
-      ]
-    },
-    "BigBrain Cortical Layers Segmentation": {
-      url: "/?templateSelected=Big+Brain+%28Histology%29&parcellationSelected=BigBrain+Cortical+Layers+Segmentation&cNavigation=0.0.0.-W000.._eCwg.2-FUe3._-s_W.2_evlu..7LIx..2c8U8.1FYC.wfmi..91G",
-      tests: [
-        {
-          position: [330, 550],
-          expectedLabelName: 'cortical layer 6',
-        },
-        {
-          position: [475, 244],
-          expectedLabelName: 'cortical layer 1',
-        }
-      ]
-    },
-    "Grey/White matter": {
-      url: "/?templateSelected=Big+Brain+%28Histology%29&parcellationSelected=Grey%2FWhite+matter&cNavigation=0.0.0.-W000.._eCwg.2-FUe3._-s_W.2_evlu..7LIx..3cX1m.1FYC.Cr8t..5Jn",
-      tests: [
-        {
-          position: [210, 238],
-          expectedLabelName: 'White matter'
-        },
-        {
-          position: [600, 150],
-          expectedLabelName: 'Grey matter'
-        }
-      ]
-    }
-  }
-}
-
-describe('> mouse over viewer show area name', () => {
-  let iavPage
-  beforeAll(async () => {
-    iavPage = new AtlasPage()
-    await iavPage.init()
-  })
-
-  for (const templateName in dictionary) {
-    for (const parcellationName in dictionary[templateName]) {
-      describe(`> testing template: ${templateName} & parcellation: ${parcellationName}`, () => {
-
-        const {url, tests} = dictionary[templateName][parcellationName]
-        beforeAll(async () => {
-          if (url) {
-            await iavPage.goto(url)
-          } else {
-            await iavPage.goto()
-            await iavPage.selectTitleTemplateParcellation(templateName, parcellationName)
-          }
-          
-          const tag = await iavPage.getSideNavTag()
-          await tag.click()
-          await iavPage.wait(1000)
-          await iavPage.waitUntilAllChunksLoaded()
-        })
-        for (const { position, expectedLabelName } of tests ) {          
-          it(`> at cursor position: ${JSON.stringify(position)}, expect label name: ${expectedLabelName}`, async () => {
-
-            await iavPage.cursorMoveTo({ position })
-            await iavPage.wait(2000)
-            const text = await iavPage.getFloatingCtxInfoAsText()
-            expect(
-              text.indexOf(expectedLabelName)
-            ).toBeGreaterThanOrEqual(0)
-          })
-        }
-      })
-    }
-  }
-})
diff --git a/e2e/src/navigating/navigateFromRegion.prod.e2e-spec.js b/e2e/src/navigating/navigateFromRegion.prod.e2e-spec.js
deleted file mode 100644
index 3c90b7ceb5e394c5074a10b63947ac871f66e99b..0000000000000000000000000000000000000000
--- a/e2e/src/navigating/navigateFromRegion.prod.e2e-spec.js
+++ /dev/null
@@ -1,175 +0,0 @@
-const { AtlasPage } = require('../util')
-const { ARIA_LABELS } = require('../../../common/constants')
-const { SHOW_IN_OTHER_REF_SPACE, AVAILABILITY_IN_OTHER_REF_SPACE } = ARIA_LABELS
-
-const TEST_DATA = [
-  {
-    url: "/?templateSelected=MNI+152+ICBM+2009c+Nonlinear+Asymmetric&parcellationSelected=JuBrain+Cytoarchitectonic+Atlas",
-    templateName: 'MNI 152 ICBM 2009c Nonlinear Asymmetric',
-    position: [450, 200],
-    expectedRegion: 'Area hOc1 (V1, 17, CalcS) - left hemisphere',
-    expectedTemplateLabels: [
-      {
-        name: 'Big Brain (Histology)',
-        expectedPosition: [3187941, -50436480, 3430986]
-      },
-      {
-        name: 'MNI Colin 27',
-        expectedPosition: [
-          -8533787,
-          -84646549,
-          1855106
-        ]
-      },
-    ],
-  },
-  {
-    url: "/?templateSelected=Big+Brain+%28Histology%29&parcellationSelected=Cytoarchitectonic+Maps&cNavigation=0.0.0.-W000.._eCwg.2-FUe3._-s_W.2_evlu..7LIx..1n5q~.1FYC.2Is-..1B9C",
-    templateName: 'Big Brain (Histology)',
-    position: [691,678], // [370, 150],
-    expectedRegion: 'Area STS1 (STS)',
-    expectedTemplateLabels: [
-      {
-        name: 'MNI Colin 27',
-        hemisphere: 'left hemisphere',
-        expectedPosition: [-54514755, -16753913, -5260713]
-      },
-      {
-        name: 'MNI Colin 27',
-        hemisphere: 'right hemisphere',
-        expectedPosition: [54536567, -17992636, -5712544]
-      },
-      {
-        name: 'MNI 152 ICBM 2009c Nonlinear Asymmetric',
-        hemisphere: 'left hemisphere',
-        expectedPosition: [-55442669, -18314601, -6381831]
-      },
-      {
-        name: 'MNI 152 ICBM 2009c Nonlinear Asymmetric',
-        hemisphere: 'right hemisphere',
-        expectedPosition: [52602966, -18339402, -5666868]
-      },
-    ],
-  },
-]
-
-const getBeforeEachFn = iavPage => ({ 
-  url,
-  templateName,
-  position,
- }) => async () => {
-
-  if (url) {
-    await iavPage.goto(url)
-  } else {
-    await iavPage.goto()
-    await iavPage.selectTitleTemplateParcellation(templateName)
-    await iavPage.wait(500)
-    await iavPage.waitForAsync()
-  }
-
-  const tag = await iavPage.getSideNavTag()
-  await tag.click()
-  await iavPage.wait(1000)
-  await iavPage.waitUntilAllChunksLoaded()
-  await iavPage.cursorMoveToAndClick({ position })
-
-  await iavPage.click(`[aria-label="${SHOW_IN_OTHER_REF_SPACE}"]`)
-  await iavPage.wait(500)
-}
-
-describe('> explore same region in different templates', () => {
-
-  let iavPage
-  beforeEach(async () => {
-    iavPage = new AtlasPage()
-    await iavPage.init()
-  })
-
-  describe('> moving to different reference template works', () => {
-    for (const template of TEST_DATA) {
-      const { 
-        url,
-        templateName,
-        position,
-        expectedRegion,
-        expectedTemplateLabels,
-       } = template
-
-      describe(`> testing ${templateName}`, () => {
-        beforeEach(async () => {
-          await getBeforeEachFn(iavPage)(template)()
-        })
-
-        for (const tmplLabel of expectedTemplateLabels) {
-          const { expectedPosition, name, hemisphere } = tmplLabel
-          describe(`> moving to ${name}`, () => {
-            it('> works as expected', async () => {
-
-              const otherTemplate = await iavPage.getText(`[aria-label="${SHOW_IN_OTHER_REF_SPACE}: ${name}${hemisphere ? (' - ' + hemisphere) : ''}"]`)
-              const trimmedTemplate = otherTemplate.replace(/^\s+/, '').replace(/\s+$/, '').replace(/\s+/g, ' ')
-              if (hemisphere) {
-                expect(trimmedTemplate).toEqual(`${name} (${hemisphere})`)
-              } else {
-                expect(trimmedTemplate).toEqual(name)
-              }
-      
-              await iavPage.click(`[aria-label="${SHOW_IN_OTHER_REF_SPACE}: ${name}${hemisphere ? (' - ' + hemisphere) : ''}"]`)
-              await iavPage.wait(500)
-              await iavPage.waitUntilAllChunksLoaded()
-              
-              const navState = await iavPage.getNavigationState()
-      
-              // somehow there are slight deviations (1nm in most cases)
-              // giving a tolerance of 0.1um
-              for (const idx in navState.position) {
-                expect(
-                  Math.abs(navState.position[idx] - expectedPosition[idx])
-                ).toBeLessThanOrEqual(100)
-              }
-            })
-          })
-        }
-      })
-    }
-  })
-
-  describe('> menu UI', () => {
-    const data = TEST_DATA[0]
-
-    beforeEach(async () => {
-    })
-
-    it('> dismisses when user clicks/drags outside', async () => {
-      await getBeforeEachFn(iavPage)(data)()
-      const { expectedRegion, expectedTemplateLabels, position, url, templateName } = data
-
-      await iavPage.cursorMoveToAndDrag({
-        position: [position[0], position[1] - 100],
-        delta: [50, 1]
-      })
-
-      await iavPage.wait(1000)
-
-      // should throw
-      try {
-        const otherTemplates = await iavPage.getAllOtherTemplates()
-        expect(true).toBe(false)
-      } catch(e) {
-        expect(true).toBe(true)
-      }
-    })
-
-    it('> Tooltip visible if overflowed', async () => {
-      const data2 = TEST_DATA[1]
-      await getBeforeEachFn(iavPage)(data2)()
-      const {expectedTemplateLabels} = data2
-      const desiredTemplateButton = await expectedTemplateLabels.find(el => el.name.length > 30)
-      if (desiredTemplateButton) {
-        await iavPage.cursorMoveToElement(`[aria-label="${SHOW_IN_OTHER_REF_SPACE}: ${desiredTemplateButton.name}${desiredTemplateButton.hemisphere ? (' - ' + desiredTemplateButton.hemisphere) : ''}"]`)
-        const tooltipText = await iavPage.getText('mat-tooltip-component')
-        expect(tooltipText.trim()).toContain(desiredTemplateButton.name)
-      }
-    })
-  })
-})
diff --git a/e2e/src/navigating/originDataset.prod.e2e-spec.js b/e2e/src/navigating/originDataset.prod.e2e-spec.js
deleted file mode 100644
index db6c60dd2e698ed814424910419918e778e30412..0000000000000000000000000000000000000000
--- a/e2e/src/navigating/originDataset.prod.e2e-spec.js
+++ /dev/null
@@ -1,80 +0,0 @@
-const { AtlasPage } = require("../util")
-const { ARIA_LABELS } = require('../../../common/constants')
-const { SHOW_ORIGIN_DATASET } = ARIA_LABELS
-
-const cssSelector = `[aria-label="${SHOW_ORIGIN_DATASET}"]`
-
-const dict = {
-  'ICBM 2009c Nonlinear Asymmetric': {
-    'JuBrain Cytoarchitectonic Atlas': {
-      tests: [
-        {
-          position: [600, 490],
-          expectedLabelName: 'Area 6ma (preSMA, mesial SFG) - left hemisphere',
-        }
-      ]
-    }
-  }
-}
-
-describe('origin dataset pmap', () => {
-  let iavPage
-
-  beforeAll(async () => {
-    iavPage = new AtlasPage()
-    await iavPage.init()
-  })
-
-  for (const templateName in dict) {
-    for (const parcellationName in dict[templateName]) {
-      describe(`testing template: ${templateName}, parcellation name: ${parcellationName}`, () => {
-
-        const {url, tests} = dict[templateName][parcellationName]
-        beforeAll(async () => {
-          if (url) {
-            await iavPage.goto(url)
-          } else {
-            await iavPage.goto()
-            await iavPage.selectTitleTemplateParcellation(templateName, parcellationName)
-          }
-          
-          const tag = await iavPage.getSideNavTag()
-          await tag.click()
-          await iavPage.wait(5000)
-          await iavPage.waitUntilAllChunksLoaded()
-        })
-
-        for (const test of tests) {
-          it('> original pmap btn exists, and on click, show pmap', async () => {
-
-            const { position, expectedLabelName } = test
-            await iavPage.cursorMoveToAndClick({ position })
-
-            await iavPage.click(cssSelector)
-            await iavPage.wait(5000)
-            await iavPage.waitForAsync()
-
-            const additionalLayerControlIsExpanded = await iavPage.additionalLayerControlIsExpanded()
-            expect(additionalLayerControlIsExpanded).toEqual(false)
-            
-            const checked = await iavPage.switchIsChecked(cssSelector)
-            expect(checked).toEqual(true)
-          })
-
-          it('> on second click, dismisses the pmap', async () => {
-
-            await iavPage.click(cssSelector)
-            await iavPage.wait(5000)
-            await iavPage.waitForAsync()
-
-            const additionalLayerControlIsShown = await iavPage.isVisible(`[aria-label="${ARIA_LABELS.ADDITIONAL_VOLUME_CONTROL}"]`)
-            expect(additionalLayerControlIsShown).toEqual(false)
-            
-            const checked = await iavPage.switchIsChecked(cssSelector)
-            expect(checked).toEqual(false)
-          })
-        }
-      })
-    }
-  }
-})
\ No newline at end of file
diff --git a/e2e/src/selecting/atlas.prod.e2e-spec.js b/e2e/src/selecting/atlas.prod.e2e-spec.js
deleted file mode 100644
index 370fb3e17de25d3c70a4003776184178963a559c..0000000000000000000000000000000000000000
--- a/e2e/src/selecting/atlas.prod.e2e-spec.js
+++ /dev/null
@@ -1,93 +0,0 @@
-const { AtlasPage } = require('../../util/helper')
-
-const atlases = [
-  'Waxholm Space atlas of the Sprague Dawley rat brain',
-  'Multilevel Human Atlas',
-  'Allen Mouse Common Coordinate Framework v3'
-]
-
-describe('> atlases are generally available', () => {
-  let atlasPage = new AtlasPage()
-  beforeEach(async () => {
-    atlasPage = new AtlasPage()
-    await atlasPage.init()
-  })
-  it('> on startup, there should be three atlases', async () => {
-    await atlasPage.goto()
-    const texts = await atlasPage.getAllCardsText()
-    expect(texts.sort()).toEqual(atlases.sort())
-  })
-})
-
-// describe('> generic atlas behaviours', () => {
-//   let atlasPage = new AtlasPage()
-//   beforeEach(async () => {
-//     atlasPage = new AtlasPage()
-//     await atlasPage.init()
-//   })
-//   for (const atlas of atlases) {
-//     describe(`> of ${atlas}`, () => {
-//       it('> on launch, shows atlas name as a pill', async () => {
-//         await atlasPage.goto()
-//         await atlasPage.clearAlerts()
-//         await atlasPage.setAtlasSpecifications(atlas)
-//         await atlasPage.wait(500)
-//         await atlasPage.waitUntilAllChunksLoaded()
-//         const txtArr = await atlasPage.getAllChipsText()
-//         expect(
-//           txtArr.filter(v => v.replace(/\s/g, '').length > 0).length
-//         ).toBeGreaterThan(0)
-//         console.log(`chip shows: ${txtArr.join(', ')}`)
-//       })
-//     })
-//   }
-// })
-
-// describe('> in human multi level', () => {
-//   let atlasPage = new AtlasPage()
-//   beforeAll(async () => {
-//     atlasPage = new AtlasPage()
-//     await atlasPage.init()
-//     await atlasPage.goto()
-//     await atlasPage.clearAlerts()
-//   })
-//   describe('> removal of additional layers should restore base layer', () => {
-//     it('> in mni152', async () => {
-//       await atlasPage.setAtlasSpecifications(atlases[1], [`Fibre tracts`, `Short Bundle`])
-//       await atlasPage.wait(500)
-//       await atlasPage.waitForAsync()
-
-//       const txtArr = await atlasPage.getAllChipsText()
-//       expect(
-//         txtArr.find(txt => /short bundle/i.test(txt))
-//       ).toBeTruthy()
-
-//       await atlasPage.clickChip(/short bundle/i, '.fa-times')
-
-//       const txtArr2 = await atlasPage.getAllChipsText()
-//       expect(
-//         txtArr2.find(txt => /short bundle/i.test(txt))
-//       ).toBeFalsy()
-      
-//     })
-
-//     it('> in bigbrain', async () => {
-//       await atlasPage.setAtlasSpecifications(atlases[1], [/isocortex/i])
-//       await atlasPage.wait(500)
-//       await atlasPage.waitForAsync()
-
-//       const txtArr = await atlasPage.getAllChipsText()
-//       expect(
-//         txtArr.find(txt => /isocortex/i.test(txt))
-//       ).toBeTruthy()
-
-//       await atlasPage.clickChip(/isocortex/i, '.fa-times')
-
-//       const txtArr2 = await atlasPage.getAllChipsText()
-//       expect(
-//         txtArr2.find(txt => /isocortex/i.test(txt))
-//       ).toBeFalsy()
-      
-//     })
-//   })
-// })
diff --git a/e2e/src/selecting/region.prod.e2e-spec.js b/e2e/src/selecting/region.prod.e2e-spec.js
deleted file mode 100644
index 9b6e0d535042a9346c0891fe2a5da75d06daee4c..0000000000000000000000000000000000000000
--- a/e2e/src/selecting/region.prod.e2e-spec.js
+++ /dev/null
@@ -1,78 +0,0 @@
-const { AtlasPage } = require('../../src/util')
-const { height, width } = require('../../opts')
-const { CONST } = require('../../../common/constants')
-
-describe('> selecting regions', () => {
-
-  const duplicatedRegion = {
-    atlas: 'Multilevel Human Atlas',
-    template: `ICBM 152 2009c Nonlinear Asymmetric`,
-    parcVersion: 'v1.18',
-    position: [-0.256, 26.028, -11.678]
-  }
-  describe(`> when selecting duplicated regions at ${duplicatedRegion.atlas} / ${duplicatedRegion.template} / ${JSON.stringify(duplicatedRegion.position)}`, () => {
-    it(`> when click, should only select a single region`, async () => {
-      const newPage = new AtlasPage()
-      await newPage.init()
-      await newPage.goto()
-      await newPage.setAtlasSpecifications(duplicatedRegion.atlas, [ duplicatedRegion.template ], duplicatedRegion.parcVersion)
-      await newPage.wait(500)
-      await newPage.waitForAsync()
-      await newPage.execScript(`interactiveViewer.viewerHandle.setNavigationLoc(${JSON.stringify(duplicatedRegion.position.map(v => v*1e6))}, true)`)
-      await newPage.wait(500)
-      await newPage.cursorMoveTo({
-        position: [ width * 3 / 4, height / 4 ]
-      })
-      await newPage.wait(500)
-      const txt = await newPage.getText(`[floatingMouseContextualContainerDirective]`)
-      expect(txt.indexOf(`left`)).toBeGreaterThanOrEqual(0)
-      expect(txt.indexOf(`right`)).toBeGreaterThanOrEqual(0)
-
-      await newPage.cursorMoveToAndClick({
-        position: [width * 3 / 4, height / 4]
-      })
-      await newPage.wait(500)
-      await newPage.waitForAsync()
-      const visible = await newPage.areVisible(`region-menu`)
-      expect(visible.length).toEqual(1)
-
-    })
-  })
-
-  describe('> [bkwdCompat] multi region select is handled gracefully', () => {
-    const url = `?templateSelected=Waxholm+Space+rat+brain+MRI%2FDTI&parcellationSelected=Waxholm+Space+rat+brain+atlas+v2&cRegionsSelected=%7B%22v2%22%3A%2213.a.b.19.6.c.q.x.1.1L.Y.1K.r.s.y.z._.1G.-.Z.18.v.f.g.1J.1C.k.14.15.7.1E.1F.10.11.12.1D.1S.A.1V.1W.1X.1Y.1Z.1a.1i.1j.1k.1m.1n.1o.1p.U.V.W.3.1I.e.d.1T.1H.m.h.n.1U.o.t.2.17.p.w.4.5.1A.1B.u.l.j.16%22%7D&cNavigation=0.0.0.-W000..2-8Bnd.2_tvb9._yymE._tYzz..1Sjt..9Hnn%7E.Lqll%7E.Vcf..9fo`
-
-    const humanAtlasName = `Multilevel Human Atlas`
-    let newPage = new AtlasPage()
-    beforeAll(async () => {
-      await newPage.init()
-      await newPage.goto(url)
-      /**
-       * clear cookie alert
-       */
-      await newPage.clearAlerts()
-      await newPage.wait(500)
-      /**
-       * clear KG ToS alert
-       */
-      await newPage.clearAlerts()
-    })
-    it('> handles waxholm v2 whole brains election', async () => {
-      const allChipsVisibility = await newPage.getAllChipsVisibility()
-      expect(allChipsVisibility.filter(v => !!v).length).toEqual(2)
-      const allChipsText = await newPage.getAllChipsText()
-      expect(allChipsText).toContain(CONST.MULTI_REGION_SELECTION)
-    })
-
-    it('> on change atlas, multi region panel are dismissed', async () => {
-      await newPage.setAtlasSpecifications(humanAtlasName)
-      await newPage.wait(500)
-      await newPage.waitForAsync()
-
-      const allChipsVisibility = await newPage.getAllChipsVisibility()
-      expect(allChipsVisibility.filter(v => !!v).length).toEqual(1)
-      const allChipsText = await newPage.getAllChipsText()
-      expect(allChipsText).not.toContain(CONST.MULTI_REGION_SELECTION)
-    })
-  })
-})
diff --git a/e2e/src/selecting/share.e2e-screenshot.js b/e2e/src/selecting/share.e2e-screenshot.js
deleted file mode 100644
index 35d8872c4b53002c9053eb4831bd394775ac6e40..0000000000000000000000000000000000000000
--- a/e2e/src/selecting/share.e2e-screenshot.js
+++ /dev/null
@@ -1,66 +0,0 @@
-const { AtlasPage } = require('../util')
-const { ARIA_LABELS } = require('../../../common/constants')
-const fs = require('fs')
-const path = require('path')
-
-const outputDir = path.join(__dirname, '../../../docs/autogen_images')
-const exists = fs.existsSync(outputDir)
-if (!exists) fs.mkdirSync(outputDir)
-
-describe('> share', () => {
-  let iavPage
-  beforeAll(async () => {
-    iavPage = new AtlasPage()
-    await iavPage.init()
-    await iavPage.goto()
-    await iavPage.wait(1000)
-    await iavPage.selectTitleTemplateParcellation('Big Brain (Histology)', 'Grey/White matter')
-    await iavPage.wait(1000)
-    await iavPage.waitUntilAllChunksLoaded()
-  })
-
-  afterEach(async () => {
-    await iavPage.clearAlerts()
-  })
-
-  it('> generating highlight share btn', async () => {
-    const b64 = await iavPage.takeScreenshot(`[aria-label="${ARIA_LABELS.SHARE_BTN}"]`)
-
-    const outputPath = path.join(outputDir, 'share_highlightShareBtn.png')
-    fs.writeFileSync(outputPath, b64, 'base64')
-  })
-
-  it('> generating highlight shareUrl btn', async () => {
-    await iavPage.click(`[aria-label="${ARIA_LABELS.SHARE_BTN}"]`)
-    await iavPage.wait(1000)
-
-    const b64 = await iavPage.takeScreenshot(`[aria-label="${ARIA_LABELS.SHARE_COPY_URL_CLIPBOARD}"]`)
-
-    const outputPath = path.join(outputDir, 'share_highlightShareURL.png')
-    fs.writeFileSync(outputPath, b64, 'base64')
-  })
-
-  it('> generating highlight custom URL', async () => {
-
-    await iavPage.click(`[aria-label="${ARIA_LABELS.SHARE_BTN}"]`)
-    await iavPage.wait(1000)
-
-    const b64 = await iavPage.takeScreenshot(`[aria-label="${ARIA_LABELS.SHARE_CUSTOM_URL}"]`)
-
-    const outputPath = path.join(outputDir, 'share_highlightShareCustomURL.png')
-    fs.writeFileSync(outputPath, b64, 'base64')
-  })
-
-  it('> generating custom URL dialog', async () => {
-
-    await iavPage.click(`[aria-label="${ARIA_LABELS.SHARE_BTN}"]`)
-    await iavPage.wait(1000)
-    await iavPage.click(`[aria-label="${ARIA_LABELS.SHARE_CUSTOM_URL}"]`)
-    await iavPage.wait(1000)
-
-    const b64 = await iavPage.takeScreenshot(`[aria-label="${ARIA_LABELS.SHARE_CUSTOM_URL_DIALOG}"]`)
-
-    const outputPath = path.join(outputDir, 'share_shareCustomURLDialog.png')
-    fs.writeFileSync(outputPath, b64, 'base64')
-  })
-})
diff --git a/e2e/src/selecting/template.prod.e2e-spec.js b/e2e/src/selecting/template.prod.e2e-spec.js
deleted file mode 100644
index 23e378a03c1bc12ceb1994a4bbb5ea7ffe256450..0000000000000000000000000000000000000000
--- a/e2e/src/selecting/template.prod.e2e-spec.js
+++ /dev/null
@@ -1,108 +0,0 @@
-const { isatty } = require("tty")
-const { AtlasPage } = require("../util")
-
-const atlasName = 'Multilevel Human Atlas'
-const tNameIcbm152 = 'ICBM 152 2009c Nonlinear Asymmetric'
-// colin has temporarily been disabled
-// const tNameColin = 'MNI Colin 27'
-const tNameBB = 'Big Brain (Histology)'
-
-describe('templates > ', () => {
-
-  let iavPage
-  beforeEach(async () => {
-    iavPage = new AtlasPage()
-    await iavPage.init()
-  })
-
-  describe('selecting template', () => {
-    
-    it('can select template by clicking main card', async () => {
-      await iavPage.goto()
-      await iavPage.setAtlasSpecifications(atlasName)
-      await iavPage.wait(1000)
-  
-      const viewerIsPopulated = await iavPage.viewerIsPopulated()
-      expect(viewerIsPopulated).toBe(true)
-    })
-    
-  
-    it('switching template after template init by clicking select should work', async () => {
-  
-      await iavPage.goto()
-  
-      await iavPage.setAtlasSpecifications(atlasName, [ tNameIcbm152 ])
-      await iavPage.wait(1000)
-  
-      await iavPage.setAtlasSpecifications(atlasName, [ tNameBB ])
-      await iavPage.wait(7000)
-  
-      const viewerIsPopulated = await iavPage.viewerIsPopulated()
-      expect(viewerIsPopulated).toBe(true)
-    })
-  
-    it('MNI152 should return desc', async () => {
-  
-      const expectedDesc = `An unbiased non-linear average of multiple subjects from the MNI152 database, which provides high-spatial resolution and signal-to-noise while not being biased towards a single brain (Fonov et al., 2011). This template space is widely used as a reference space in neuroimaging. HBP provides the JuBrain probabilistic cytoarchitectonic atlas (Amunts/Zilles, 2015) as well as a probabilistic atlas of large fibre bundles (Guevara, Mangin et al., 2017) in this space.`
-  
-      await iavPage.goto()
-  
-      await iavPage.setAtlasSpecifications(atlasName, [ tNameIcbm152 ])
-      await iavPage.wait(1000)
-  
-      const info = await iavPage.getAtlasTileInfo(tNameIcbm152)
-  
-      expect(
-        info.indexOf(expectedDesc)
-      ).toBeGreaterThanOrEqual(0)
-    })
-  })
-  
-  describe('> switching template', () => {
-    beforeEach(async () => {
-
-      await iavPage.goto()
-      await iavPage.setAtlasSpecifications(atlasName, [ tNameIcbm152 ])
-      await iavPage.wait(500)
-      await iavPage.waitUntilAllChunksLoaded()
-    })
-    it('> activeFlag works', async () => {
-      const isActive = await iavPage.atlasTileIsActive(tNameIcbm152)
-      expect(isActive.toString()).toEqual('true')
-      const isNotActive = await iavPage.atlasTileIsActive(tNameBB)
-      expect(isNotActive.toString()).toEqual('false')
-
-    })
-    it('> works in regular navigation', async () => {
-
-      await iavPage.setAtlasSpecifications(atlasName, [ tNameIcbm152 ])
-      await iavPage.wait(500)
-      await iavPage.waitUntilAllChunksLoaded()
-      await iavPage.wait(500)
-      
-      const isActive = await iavPage.atlasTileIsActive(tNameIcbm152)
-      expect(isActive.toString()).toEqual('true')
-
-      const isNotActive = await iavPage.atlasTileIsActive(tNameBB)
-      expect(isNotActive.toString()).toEqual('false')
-
-    })
-
-    it('> works in history navigation', async () => {
-
-      await iavPage.setAtlasSpecifications(atlasName, [ tNameBB ])
-      await iavPage.wait(500)
-      await iavPage.waitUntilAllChunksLoaded()
-      
-      await iavPage.historyBack()
-      await iavPage.wait(500)
-      await iavPage.waitForAsync()
-
-      const isActive = await iavPage.atlasTileIsActive(tNameIcbm152)
-      expect(isActive.toString()).toEqual('true')
-      const isNotActive = await iavPage.atlasTileIsActive(tNameBB)
-      expect(isNotActive.toString()).toEqual('false')
-    })
-  })
-
-})
\ No newline at end of file
diff --git a/e2e/src/util.js b/e2e/src/util.js
deleted file mode 100644
index f837b8ce9285bb77d0416738d39c6c79e1efb13e..0000000000000000000000000000000000000000
--- a/e2e/src/util.js
+++ /dev/null
@@ -1,10 +0,0 @@
-
-const {
-  BasePage,
-  AtlasPage,
-  LayoutPage,
-} = require('../util/helper')
-
-exports.AtlasPage = AtlasPage
-exports.LayoutPage = LayoutPage
-exports.BasePage = BasePage
diff --git a/e2e/util/helper.js b/e2e/util/helper.js
deleted file mode 100644
index 10a7176ad2c2428057a87561e0e1427f76e5ea84..0000000000000000000000000000000000000000
--- a/e2e/util/helper.js
+++ /dev/null
@@ -1,11 +0,0 @@
-const {
-  WdIavPage,
-  WdLayoutPage,
-  WdBase,
-} = require('./selenium/iav')
-
-module.exports = {
-  BasePage: WdBase,
-  LayoutPage: WdLayoutPage,
-  AtlasPage: WdIavPage
-}
diff --git a/e2e/util/selenium/base.js b/e2e/util/selenium/base.js
deleted file mode 100644
index 88312daf3cd2eadb52f2b47a390e9d1e6d33c89b..0000000000000000000000000000000000000000
--- a/e2e/util/selenium/base.js
+++ /dev/null
@@ -1,413 +0,0 @@
-const CITRUS_LIGHT_URL = `https://unpkg.com/citruslight@0.1.0/citruslight.js`
-const { By, Key, until } = require('selenium-webdriver')
-const { retry } = require('../../../common/util')
-const chromeOpts = require('../../chromeOpts')
-const ATLAS_URL = (process.env.ATLAS_URL || 'http://localhost:3000').replace(/\/$/, '')
-
-function getActualUrl(url) {
-  return /^http\:\/\//.test(url) ? url : `${ATLAS_URL}/${url.replace(/^\//, '')}`
-}
-
-async function polyFillClick(cssSelector){
-  if (!cssSelector) throw new Error(`click method needs to define a css selector`)
-  const webEl = this._browser.findElement( By.css(cssSelector) )
-  try {
-    await webEl.click()
-  } catch (e) {
-    const id = await webEl.getAttribute('id')
-    const newId = id.replace(/-input$/, '')
-    await this._browser.findElement(
-      By.id(newId)
-    ).click()
-  }
-}
-
-const verifyPosition = position => {
-
-  if (!position) throw new Error(`cursorGoto: position must be defined!`)
-  const x = Array.isArray(position) ? position[0] : position.x
-  const y = Array.isArray(position) ? position[1] : position.y
-  if (!x) throw new Error(`cursorGoto: position.x or position[0] must be defined`)
-  if (!y) throw new Error(`cursorGoto: position.y or position[1] must be defined`)
-
-  return {
-    x,
-    y
-  }
-}
-
-class WdBase{
-  constructor() {
-    browser.waitForAngularEnabled(false)
-    globalThis.IAVBase = this
-  }
-  get _browser(){
-    return browser
-  }
-  get _driver(){
-    return this._browser.driver
-  }
-
-  async highlightElement(cssSelector) {
-
-    await this._browser.executeAsyncScript(async () => {
-      const cb = arguments[arguments.length - 1]
-      const moduleUrl = arguments[0]
-      const cssSelector = arguments[1]
-
-      const el = document.querySelector(cssSelector)
-      if (!el) throw new Error(`css selector not fetching anything`)
-      import(moduleUrl)
-        .then(async m => {
-          m.citruslight(el)
-          cb()
-        })
-    }, CITRUS_LIGHT_URL, cssSelector)
-
-    await this.wait(1000)
-
-    return async () => {
-      await this._browser.executeAsyncScript(async () => {
-        const cb = arguments[arguments.length - 1]
-        const moduleUrl = arguments[0]
-
-        import(moduleUrl)
-          .then(async m => {
-            m.clearAll()
-            cb()
-          })
-      }, CITRUS_LIGHT_URL)
-    }
-  }
-
-  // without image header
-  // output as b64 png
-  async takeScreenshot(cssSelector){
-    
-    let cleanUp
-    if(cssSelector) {
-      cleanUp= await this.highlightElement(cssSelector)
-    }
-    
-    const result = await this._browser.takeScreenshot()
-
-    if (cleanUp) {
-      await cleanUp()
-    }
-    
-    await this.wait(1000)
-    return result
-  }
-
-  async getLog() {
-    const browserLog = await this._browser.manage().logs().get('browser')
-    return browserLog
-  }
-
-  async getRgbAt({ position } = {}, cssSelector = null){
-    if (!position) throw new Error(`position is required for getRgbAt`)
-    const { x, y } = verifyPosition(position)
-    const screenshotData = await this.takeScreenshot(cssSelector)
-    const [ red, green, blue ] = await this._driver.executeAsyncScript(() => {
-      
-      const dataUri = arguments[0]
-      const pos = arguments[1]
-      const dim = arguments[2]
-      const cb = arguments[arguments.length - 1]
-
-      const img = new Image()
-      img.onload = () => {
-        const canvas = document.createElement('canvas')
-        canvas.width = dim[0]
-        canvas.height = dim[1]
-
-        const ctx = canvas.getContext('2d')
-        ctx.drawImage(img, 0, 0)
-        const imgData = ctx.getImageData(0, 0, dim[0], dim[1])
-
-        const idx = (dim[0] * pos[1] + pos[0]) * 4
-        const red = imgData.data[idx]
-        const green = imgData.data[idx + 1]
-        const blue = imgData.data[idx + 2]
-        cb([red, green, blue])
-      }
-      img.src = dataUri
-
-    }, `data:image/png;base64,${screenshotData}`, [x, y], [800, 796])
-
-    return { red, green, blue }
-  }
-
-  async switchIsChecked(cssSelector){
-    if (!cssSelector) throw new Error(`switchChecked method requies css selector`)
-    const checked = await this._browser
-      .findElement( By.css(cssSelector) )
-      .getAttribute('aria-checked')
-    return checked === 'true'
-  }
-
-  async click(cssSelector){
-    return await polyFillClick.bind(this)(cssSelector)
-  }
-
-  async getText(cssSelector){
-    if (!cssSelector) throw new Error(`getText needs to define css selector`)
-    const el = await this._browser.findElement( By.css(cssSelector) )
-    
-    const text = await el.getText()
-    return text
-  }
-
-  async isVisible(cssSelector) {
-
-    if (!cssSelector) throw new Error(`getText needs to define css selector`)
-    const el = await this._browser.findElement( By.css(cssSelector) )
-    const isDisplayed = await el.isDisplayed()
-
-    return isDisplayed
-  }
-
-  async areVisible(cssSelector){
-    if (!cssSelector) throw new Error(`getText needs to define css selector`)
-    const els = await this._browser.findElements( By.css( cssSelector ) )
-    const returnArr = []
-
-    for (const el of els) {
-      returnArr.push(await el.isDisplayed())
-    }
-    return returnArr
-  }
-
-  async isAt(cssSelector){
-    if (!cssSelector) throw new Error(`getText needs to define css selector`)
-    const { x, y, width, height } = await this._browser.findElement( By.css(cssSelector) ).getRect()
-    return { x, y, width, height }
-  }
-
-  async areAt(cssSelector){
-
-    if (!cssSelector) throw new Error(`getText needs to define css selector`)
-    const els = await this._browser.findElements( By.css( cssSelector ) )
-    const returnArr = []
-
-    for (const el of els) {
-      const { x, y, width, height } = await el.getRect()
-      returnArr.push({ x, y, width, height })
-    }
-    return returnArr
-  }
-
-  historyBack() {
-    return this._browser.navigate().back()
-  }
-
-  historyForward() {
-    return this._browser.navigate().forward()
-  }
-
-  async init() {
-    const wSizeArg = chromeOpts.find(arg => arg.indexOf('--window-size') >= 0)
-    const [ _, width, height ] = /\=([0-9]{1,})\,([0-9]{1,})$/.exec(wSizeArg)
-
-    const newDim = await this._browser.executeScript(async () => {
-      return [
-        window.outerWidth - window.innerWidth + (+ arguments[0]),
-        window.outerHeight - window.innerHeight + (+ arguments[1]),
-      ]
-    }, width, height)
-
-    await this._browser.manage()
-      .window()
-      .setRect({
-        width: newDim[0],
-        height: newDim[1]
-      })
-  }
-
-  async waitForAsync(){
-
-    await this._browser.wait(async () => {
-      const els = await this._browser.findElements(
-        By.css('div.loadingIndicator')
-      )
-      const els2 = await this._browser.findElements(
-        By.css('.spinnerAnimationCircle')
-      )
-      return [...els, ...els2].length === 0
-    }, 1e3 * 60 * 10)
-  }
-
-  async cursorMoveTo({ position }) {
-    const { x, y } = verifyPosition(position)
-    return this._driver.actions()
-      .move()
-      .move({
-        x,
-        y,
-        duration: 1000
-      })
-      .perform()
-  }
-
-  async cursorMoveToElement(cssSelector) {
-    if (!cssSelector) throw new Error(`cursorMoveToElement needs to define css selector`)
-    const el = await this._browser.findElement( By.css(cssSelector) )
-    await this._driver.actions()
-      .move()
-      .move({
-        origin: el,
-        duration: 1000
-      })
-      .perform()
-  }
-
-  async scrollElementBy(cssSelector, options) {
-    const { delta } = options
-    await this._browser.executeScript(() => {
-      const { delta } = arguments[1]
-      const el = document.querySelector(arguments[0])
-      el.scrollBy(...delta)
-    }, cssSelector, { delta })
-  }
-
-  async getScrollStatus(cssSelector) {
-    const val = await this._browser.executeScript(() => {
-      const el = document.querySelector(arguments[0])
-      return el.scrollTop
-    }, cssSelector)
-    return val
-  }
-
-  async cursorMoveToAndClick({ position }) {
-    const { x, y } = verifyPosition(position)
-    return this._driver.actions()
-      .move()
-      .move({
-        x,
-        y,
-        duration: 1000
-      })
-      .click()
-      .perform()
-  }
-
-  async cursorMoveToAndDrag({ position, delta }) {
-    const { x, y } = verifyPosition(position)
-    const { x: deltaX, y: deltaY } = verifyPosition(delta)
-    return this._driver.actions()
-      .move()
-      .move({
-        x,
-        y,
-        duration: 1000
-      })
-      .press()
-      .move({
-        x: x + deltaX,
-        y: y + deltaY,
-        duration: 1000
-      })
-      .release()
-      .perform()
-  }
-
-  async initHttpInterceptor(){
-    await this._browser.executeScript(() => {
-      if (window.__isIntercepting__) return
-      window.__isIntercepting__ = true
-      const open = window.XMLHttpRequest.prototype.open
-      window.__interceptedXhr__ = []
-      window.XMLHttpRequest.prototype.open = function () {
-        window.__interceptedXhr__.push({
-          method: arguments[0],
-          url: arguments[1]
-        })
-        return open.apply(this, arguments)
-      }
-    })
-  }
-
-  async isHttpIntercepting(){
-    return await this._browser.executeScript(() => {
-      return window.__isIntercepting__
-    })
-  }
-
-  async getInterceptedHttpCalls(){
-    return await this._browser.executeScript(() => {
-      return window['__interceptedXhr__']
-    })
-  }
-
-  // it seems if you set intercept http to be true, you might also want ot set do not automat to be true
-  async goto(url = '/', { interceptHttp, doNotAutomate, forceTimeout = 20 * 1000 } = {}){
-    this.__trackingNavigationState__ = false
-    const actualUrl = getActualUrl(url)
-    if (interceptHttp) {
-      this._browser.get(actualUrl)
-      await this.initHttpInterceptor() 
-    } else {
-      await this._browser.get(actualUrl)
-    }
-
-    // if doNotAutomate is not set
-    // should wait for async operations to end 
-    if (!doNotAutomate) {
-      await this.wait(200)
-      await this.clearAlerts()
-      await this.wait(200)
-
-      if (forceTimeout) {
-        await Promise.race([
-          this.waitForAsync(),
-          this.wait(forceTimeout)
-        ])
-      } else {
-        await this.waitForAsync()
-      }
-    }
-  }
-
-  async wait(ms) {
-    if (!ms) throw new Error(`wait duration must be specified!`)
-    return new Promise(rs => {
-      setTimeout(rs, ms)
-    })
-  }
-
-  async waitForCss(cssSelector) {
-    if (!cssSelector) throw new Error(`css selector must be defined`)
-    await this._browser.wait(
-      until.elementLocated( By.css(cssSelector) ),
-      1e3 * 60 * 10
-    )
-  }
-
-  async waitFor(animation = false, async = false){
-    if (animation) await this.wait(500)
-    if (async) await this.waitForAsync()
-  }
-
-  async clearAlerts() {
-    await this._driver
-      .actions()
-      .sendKeys(
-        Key.ESCAPE,
-        Key.ESCAPE,
-        Key.ESCAPE,
-        Key.ESCAPE
-      )
-      .perform()
-
-    await this.wait(500)
-  }
-
-  async execScript(fn, ...arg){
-    const result = await this._driver.executeScript(fn)
-    return result
-  }
-}
-
-module.exports = {
-  WdBase
-}
diff --git a/e2e/util/selenium/iav.js b/e2e/util/selenium/iav.js
deleted file mode 100644
index 6d75eaa5b7b3ed38e1310d7460fdd24ef874aac2..0000000000000000000000000000000000000000
--- a/e2e/util/selenium/iav.js
+++ /dev/null
@@ -1,200 +0,0 @@
-const { WdLayoutPage, WdBase } = require('./layout')
-const { ARIA_LABELS, CONST } = require('../../../common/constants')
-const { _getTextFromWebElement, _getIndexFromArrayOfWebElements } = require('./util')
-const { Key } = require('selenium-webdriver')
-
-class WdIavPage extends WdLayoutPage{
-  constructor(){
-    super()
-  }
-
-  async clearAllSelectedRegions() {
-    const clearAllRegionBtn = await this._browser.findElement(
-      By.css(`[aria-label="${ARIA_LABELS.CLEAR_SELECTED_REGION}"]`)
-    )
-    await clearAllRegionBtn.click()
-    await this.wait(500)
-  }
-
-  async waitUntilAllChunksLoaded(){
-    await this.waitForCss(`iav-cmp-viewer-nehuba-glue`)
-    await this.waitForAsync()
-  }
-
-  async getFloatingCtxInfoAsText(){
-    const floatingContainer = await this._browser.findElement(
-      By.css('div[floatingMouseContextualContainerDirective]')
-    )
-
-    const text = await floatingContainer.getText()
-    return text
-  }
-
-  async selectDropdownTemplate(title) {
-    throw new Error(`selectDropdownTemplate has been deprecated. use setAtlasSpecifications instead`)
-  }
-
-  async _getSearchRegionInput(){
-    await this._setSideNavPrimaryExpanded(true)
-    await this.wait(500)
-    const secondaryOpen = await this._getSideNavSecondaryExpanded()
-    if (secondaryOpen) {
-      return this._getSideNavSecondary().findElement( By.css(`[aria-label="${ARIA_LABELS.TEXT_INPUT_SEARCH_REGION}"]`) )
-    } else {
-      return this._getSideNavPrimary().findElement( By.css(`[aria-label="${ARIA_LABELS.TEXT_INPUT_SEARCH_REGION}"]`) )
-    }
-  }
-
-  async searchRegionWithText(text=''){
-    const searchRegionInput = await this._getSearchRegionInput()
-    await searchRegionInput
-      .sendKeys(
-        Key.chord(Key.CONTROL, 'a'),
-        text
-      )
-  }
-
-  async clearSearchRegionWithText() {
-    const searchRegionInput = await this._getSearchRegionInput()
-    await searchRegionInput
-      .sendKeys(
-        Key.chord(Key.CONTROL, 'a'),
-        Key.BACK_SPACE,
-        Key.ESCAPE
-      )
-  }
-
-  async _getAutcompleteOptions(){
-    const input = await this._getSearchRegionInput()
-    const autocompleteId = await input.getAttribute('aria-owns')
-    const el = await this._browser.findElement( By.css( `[id=${autocompleteId}]` ) )
-    return this._browser
-      .findElement( By.id( autocompleteId ) )
-      .findElements( By.tagName('mat-option') )
-  }
-
-  async getSearchRegionInputAutoCompleteOptions(){
-    const options = await this._getAutcompleteOptions()
-    return await Promise.all(
-      options.map(_getTextFromWebElement)
-    )
-  }
-
-  async selectSearchRegionAutocompleteWithText(text = ''){
-
-    const options = await this._getAutcompleteOptions()
-
-    const idx = await _getIndexFromArrayOfWebElements(text, options)
-    if (idx >= 0) {
-      await options[idx].click()
-    } else {
-      throw new Error(`_getIndexFromArrayOfWebElements ${text} option not founds`)
-    }
-  }
-
-  _getModalityListView(){
-    return this._browser
-      .findElement( By.css('modality-picker') )
-      .findElements( By.css('mat-checkbox') )
-  }
-
-  async getModalities(){
-    const els = await this._getModalityListView()
-    const returnArr = []
-    for (const el of els) {
-      returnArr.push(
-        await el.getText()
-      )
-    }
-    return returnArr
-  }
-
-  _getSingleDatasetListView(){
-    throw new Error(`data-browser has been deprecated. rewrite selector`)
-    return this._browser
-      .findElement( By.css('data-browser') )
-      .findElements( By.css('single-dataset-list-view') )
-  }
-
-  async getVisibleDatasets() {
-    const singleDatasetListView = await this._getSingleDatasetListView()
-
-    const returnArr = []
-    for (const item of singleDatasetListView) {
-      returnArr.push( await item.getText() )
-    }
-    return returnArr
-  }
-
-  async clickNthDataset(index){
-    if (!Number.isInteger(index)) throw new Error(`index needs to be an integer`)
-    const list = await this._getSingleDatasetListView()
-    await list[index].click()
-  }
-
-  async togglePinNthDataset(index) {
-    if (!Number.isInteger(index)) throw new Error(`index needs to be an integer`)
-    const list = await this._getSingleDatasetListView()
-    if (!list[index]) throw new Error(`out of bound ${index} in list with length ${list.length}`)
-    await list[index]
-      .findElement( By.css('[aria-label="Toggle pinning this dataset"]') )
-      .click()
-  }
-
-  async viewerIsPopulated() {
-    try {
-      const ngContainer = await this._browser.findElement(
-        By.id('neuroglancer-container')
-      )
-      if (! (await ngContainer.isDisplayed())) {
-        return false
-      }
-      const canvas = await ngContainer.findElement(
-        By.tagName('canvas')
-      )
-      if (!(await canvas.isDisplayed())) {
-        return false
-      }
-      return true
-    } catch (e) {
-      return false
-    }
-  }
-
-  async getNavigationState() {
-    if (!this.__trackingNavigationState__) {
-      await this._browser.executeScript(async () => {
-        window.__iavE2eNavigationState__ = {}
-        
-        const getPr = () => new Promise(rs => {
-  
-          window.__iavE2eNavigationStateSubptn__ = nehubaViewer.navigationState.all
-            .subscribe(({ orientation, perspectiveOrientation, perspectiveZoom, position, zoom }) => {
-              window.__iavE2eNavigationState__ = {
-                orientation: Array.from(orientation),
-                perspectiveOrientation: Array.from(perspectiveOrientation),
-                perspectiveZoom,
-                zoom,
-                position: Array.from(position)
-              }
-              rs()
-            })
-        })
-  
-        await getPr()
-      })
-
-      this.__trackingNavigationState__ = true
-    }
-
-    const returnVal = await this._browser.executeScript(() => window.__iavE2eNavigationState__)
-    return returnVal
-  }
-
-}
-
-module.exports = {
-  WdIavPage,
-  WdLayoutPage,
-  WdBase,
-}
\ No newline at end of file
diff --git a/e2e/util/selenium/layout.js b/e2e/util/selenium/layout.js
deleted file mode 100644
index 27f1f6e15d88cb4afa500609f1c49e62c7ad586b..0000000000000000000000000000000000000000
--- a/e2e/util/selenium/layout.js
+++ /dev/null
@@ -1,665 +0,0 @@
-const { WdBase } = require('./base')
-const {
-  _getIndexFromArrayOfWebElements,
-  _getTextFromWebElement,
-  _compareText
-} = require('./util')
-const { ARIA_LABELS } = require('../../../common/constants')
-
-class WdLayoutPage extends WdBase{
-  constructor(){
-    super()
-  }
-
-  /**
-   * Dropdown
-   */
-  /**
-   * 
-   * @param {string} cssSelector for the mat-select DOM element 
-   * @param {string|RegExp} optionStrRegExp substring that option's text node contains, or regexp whose .test method will be called on text node of the option
-   * @returns void
-   * @description finds a mat-select DOM element, then selects a mat-option attached to the mat-select element
-   */
-  async selectDropdownOption(cssSelector, optionStrRegExp){
-    if (!cssSelector) throw new Error(`cssSelector is required for selectDropdownOption method`)
-    const selectEl = await this._browser.findElement(
-      By.css(cssSelector)
-    )
-    if (!selectEl) throw new Error(`element with ${cssSelector} could not be found`)
-    const tagName = await selectEl.getTagName()
-    if (tagName !== 'mat-select') throw new Error(`cssSelector ${cssSelector} did not return a mat-select element, but returned a tagName element`)
-    await selectEl.click()
-    await this.wait(500)
-    const ariaOwnsAttr = await selectEl.getAttribute('aria-owns')
-
-    const opts = []
-    for (const ariaOwnEntry of ariaOwnsAttr.split(' ')) {
-      const matOpt = await this._browser.findElement(
-        By.css(`mat-option#${ariaOwnEntry}`)
-      )
-      const txt = await matOpt.getText()
-      if (_compareText(txt, optionStrRegExp)) {
-        await matOpt.click()
-        return
-      }
-    }
-    throw new Error(`option ${optionStrRegExp} not found.`)
-  }
-
-  /**
-   * Snackbar
-   */
-  async getSnackbarMessage(){
-    const txt = await this._driver
-      .findElement( By.css('simple-snack-bar') )
-      .findElement( By.css('span') )
-      .getText()
-    return txt
-  }
-
-  async clickSnackbarAction(){
-    await this._driver
-      .findElement( By.css('simple-snack-bar') )
-      .findElement( By.css('button') )
-      .click()
-  }
-
-  /**
-   * Bottomsheet
-   */
-  _getBottomSheet() {
-    return this._driver.findElement( By.css('mat-bottom-sheet-container') )
-  }
-
-  _getBottomSheetList(){
-    return this._getBottomSheet().findElements( By.css('mat-list-item') )
-  }
-
-  async getBottomSheetList(){
-    const listItems = await this._getBottomSheetList()
-    const output = []
-    for (const item of listItems) {
-      output.push(
-        await _getTextFromWebElement(item)
-      )
-    }
-    return output
-  }
-
-  async clickNthItemFromBottomSheetList(index, cssSelector){
-
-    const list = await this._getBottomSheetList()
-
-    if (!list[index]) throw new Error(`index out of bound: ${index} in list with size ${list.length}`)
-
-    if (cssSelector) {
-      await list[index]
-        .findElement( By.css(cssSelector) )
-        .click()
-    } else {
-      await list[index].click()
-    }
-  }
-
-  /**
-   * Modal
-   */
-  _getModal(){
-    return this._browser.findElement( By.css('mat-dialog-container') )
-  }
-
-  async dismissModal() {
-    try {
-      const okBtn = await this._getModal()
-        .findElement( By.css('mat-dialog-actions') )
-        .findElement( By.css('button[color="primary"]') )
-      await okBtn.click()
-    } catch (e) {
-      
-    }
-  }
-
-  _getModalBtns(){
-    return this._getModal().findElements( By.tagName('button') )
-  }
-
-  async getModalText(){
-    const el = await this._getModal()
-    const txt = await _getTextFromWebElement(el)
-    return txt
-  }
-
-  async getModalActions(){
-    const btns = await this._getModalBtns()
-
-    const arr = []
-    for (const btn of btns){
-      arr.push(await _getTextFromWebElement(btn))
-    }
-    return arr
-  }
-
-  /**
-   * 
-   * @param {string|RegExp} text 
-   * @description search criteria for the btn to click
-   */
-  async clickModalBtnByText(text){
-    const btns = await this._getModalBtns()
-    const arr = await this.getModalActions()
-    if (typeof text === 'string') {
-      const idx = arr.indexOf(text)
-      if (idx < 0) throw new Error(`clickModalBtnByText: ${text} not found.`)
-      await btns[idx].click()
-      return
-    }
-    if (text instanceof RegExp) {
-      const idx = arr.findIndex(item => text.test(item))
-      if (idx < 0) throw new Error(`clickModalBtnByText: regexp ${text.toString()} not found`)
-      await btns[idx].click()
-      return
-    }
-
-    throw new Error(`clickModalBtnByText arg must be instance of string or regexp`)
-  }
-
-  /**
-   * ExpansionPanel
-   */
-
-  /**
-   * 
-   * @param {string|RegExp} text 
-   * @description search criteria for the expansion panel title
-   */
-  async _getExpansionPanel(text){
-    const expPanels = await this._browser.findElements(
-      By.css(`mat-expansion-panel`)
-    )
-
-    const expPanelHdrs = []
-    for (const expPanel of expPanels) {
-      expPanelHdrs.push(
-        await expPanel.findElement(
-          By.css(`mat-expansion-panel-header`)
-        )
-      )
-    }
-
-    const idx = await _getIndexFromArrayOfWebElements(text, expPanelHdrs)
-    return idx >= 0 && expPanels[idx]
-  }
-
-  /**
-   * 
-   * @param {Object} expPanel webelement of the mat expansion panel
-   * @returns {Promise<boolean>} 
-   */
-  async _expansionPanelIsOpen(expPanel){
-    const classString = await expPanel.getAttribute('class')
-    /**
-     * mat-expanded gets appended when mat-expansion panel is set to open
-     */
-    return classString.indexOf('mat-expanded') >= 0
-  }
-
-  /**
-   * 
-   * @param {string|RegExp} name Text of the expansion panel header
-   * @param {boolean} flag @optional State to set the expansion panel. Leave empty for toggle.
-   */
-  async toggleExpansionPanelState(name, flag){
-    const expPanel = await this._getExpansionPanel(name)
-    if (!expPanel) throw new Error(`expansionPanel ${name} could not be found`)
-    if (typeof flag === 'undefined') {
-      await expPanel.findElement(
-        By.css(`mat-expansion-panel-header`)
-      ).click()
-      return
-    } 
-    
-    const currentOpen = await this._expansionPanelIsOpen(expPanel)
-    if (currentOpen !== flag) {
-      await expPanel.findElement(
-        By.css(`mat-expansion-panel-header`)
-      ).click()
-    }
-  }
-
-  /**
-   * Chips
-   */
-  async _getChips(){
-    return await this._browser.findElements(
-      By.css('mat-chip')
-    )
-  }
-
-  async getAllChipsText(){
-    const texts = []
-    const webEls = await this._getChips()
-    for (const el of webEls) {
-      texts.push(
-        await _getTextFromWebElement(el)
-      )
-    }
-    return texts
-  }
-
-  async getAllChipsVisibility(){
-    const visibility = []
-    const webEls = await this._getChips()
-    for (const el of webEls) {
-      visibility.push(
-        await el.isDisplayed()
-      )
-    }
-    return visibility
-  }
-
-  async clickChip(search, cssSelector) {
-    const allChips = await this._getChips()
-    const idx = await _getIndexFromArrayOfWebElements(search, allChips)
-    if (idx < 0) throw new Error(`clickChip ${search.toString()} not found`)
-    if (!cssSelector) {
-      return await allChips[idx].click()
-    }
-    const el = await allChips[idx].findElement(
-      By.css(cssSelector)
-    )
-    if (!el) throw new Error(`clickChip css selector ${cssSelector} not found`)
-    return await el.click()
-  }
-
-  /**
-   * Cards
-   */
-
-  async _getAllCards(){
-    return await this._browser.findElements(
-      By.css('mat-card')
-    )
-  }
-
-  async getAllCardsText(){
-    const allCardsEl = await this._getAllCards()
-    const txtArr = []
-    for (const el of allCardsEl) {
-      txtArr.push(
-        await _getTextFromWebElement(el)
-      )
-    }
-    return txtArr
-  }
-
-  /**
-   * Badge
-   */
-  async getBadgeContentByDesc(description){
-    const els = await this._browser.findElements(
-      By.css(`.mat-badge-content`)
-    )
-    for (const el of els) {
-      const descById = await el.getAttribute('aria-describedby')
-      if (!!descById) {
-        const descEl = await this._browser.findElement(
-          By.id(`${descById}`)
-        )
-        /**
-         * getText() will not return elements that are hidden
-         * which aria descriptions are.
-         * so use getInnerHtml instead
-         */
-        const descElText = await descEl.getAttribute('innerHTML')
-        if (descElText === description) {
-          const elText = await el.getText()
-          return elText
-        }
-      }
-    }
-    return null
-  }
-
-  /**
-   * Other
-   */
-  async _findTitleCard(title) {
-    const titleCards = await this._browser
-      .findElement( By.css('ui-splashscreen') )
-      .findElements( By.css('mat-card') )
-    const idx = await _getIndexFromArrayOfWebElements(title, titleCards)
-    if (idx >= 0) return titleCards[idx]
-    else throw new Error(`${title} does not fit any titleCards`)
-  }
-
-  async selectTitleCard( title ) {
-    const titleCard = await this._findTitleCard(title)
-    await titleCard.click()
-  }
-
-  async selectTitleTemplateParcellation(templateName, parcellationName){
-    throw new Error(`selectTitleTemplateParcellation has been deprecated. use setAtlasSpecifications`)
-  }
-
-  /**
-   * _setAtlasSelectorExpanded
-   * toggle/set the open state of the atlas-layer-selector element
-   * If the only argument (flag) is not provided, it will toggle the atlas-layer-selector
-   * 
-   * Will throw if atlas-layer-selector is not in the DOM
-   * 
-   * @param {boolean} flag 
-   * 
-   */
-  async _setAtlasSelectorExpanded(flag) {
-    const atlasLayerSelectorEl = this._browser.findElement(
-      By.css('atlas-layer-selector')
-    )
-    const openedFlag = (await atlasLayerSelectorEl.getAttribute('data-opened')) === 'true'
-    if (typeof flag === 'undefined' || flag !== openedFlag) {
-      await atlasLayerSelectorEl.findElement(By.css(`button[aria-label="${ARIA_LABELS.TOGGLE_ATLAS_LAYER_SELECTOR}"]`)).click()
-    }
-  }
-
-  /**
-   * 
-   * @param {WebElement} webEl 
-   * @description Look for child element fas.fa-info, click, then get modal text
-   */
-  async _getInfo(webEl) {
-    const infoBtn = await webEl.findElement(
-      By.css(`.fas.fa-info`)
-    )
-    if (!infoBtn) {
-      return null
-    } 
-    await infoBtn.click()
-    await this.wait(500)
-    await this.waitForAsync()
-    const text = await this.getModalText()
-    await this.clearAlerts()
-    await this.wait(500)
-    return text
-  }
-
-  async _getAtlasSelectorTile(tileName) {
-
-    if (!tileName) throw new Error(`tileName needs to be provided`)
-    await this._setAtlasSelectorExpanded(true)
-    await this.wait(1000)
-    const allTiles = await this._browser.findElements( By.css(`mat-grid-tile`) )
-
-    const idx = await _getIndexFromArrayOfWebElements(tileName, allTiles)
-
-    if (idx < 0) throw new Error(`#selectTile: tileName ${tileName} cannot be found.`)
-    return allTiles[idx]
-  }
-
-  async selectTile(tileName){
-    const el = await this._getAtlasSelectorTile(tileName)
-    await el.click()
-  }
-
-  async getAtlasTileInfo(tileName){
-    const el = await this._getAtlasSelectorTile(tileName)
-    return this._getInfo(el)
-  }
-
-  async atlasTileIsActive(tileName) {
-    const el = await this._getAtlasSelectorTile(tileName)
-    return await el.getAttribute('aria-checked')
-  }
-
-  async changeParc(parcName) {
-    throw new Error(`changeParc NYI`)
-  }
-
-  async changeParcVersion(parcVersion) {
-    await this._browser.findElement(
-      By.css(`[aria-label="${ARIA_LABELS.PARC_VER_SELECT}"]`)
-    ).click()
-    await this.wait(500)
-    this._browser.findElement(
-      By.css(`[aria-label="${ARIA_LABELS.PARC_VER_CONTAINER}"] [aria-label="${parcVersion}"]`)
-    ).click()
-    await this.wait(500)
-  }
-
-  async setAtlasSpecifications(atlasName, atlasSpecifications = [], parcVersion = null) {
-    if (!atlasName) throw new Error(`atlasName needs to be provided`)
-    try {
-      /**
-       * if at title screen
-       */
-      await (await this._findTitleCard(atlasName)).click()
-    } catch (e) {
-      /**
-       * if not at title screen
-       * select from dropdown
-       */
-      console.log(`selecting from ui-splash screen errored, try selecting from dropdown`)
-      await this.selectDropdownOption(`[aria-label="${ARIA_LABELS.SELECT_ATLAS}"]`, atlasName)
-    }
-
-    for (const spec of atlasSpecifications) {
-      await this.wait(1000)
-      await this.waitUntilAllChunksLoaded()
-      await this.selectTile(spec)
-    }
-
-    if (parcVersion) {
-      await this.wait(1000)
-      await this.waitUntilAllChunksLoaded()
-      await this.changeParcVersion(parcVersion)
-    }
-
-    try {
-      await this._setAtlasSelectorExpanded(false)
-    } catch (e) {
-      /**
-       * atlas selector may not be found
-       */
-    }
-  }
-
-  /**
-   * Sidenav
-   */
-  _getSideNavPrimary(){
-    return this._browser.findElement(
-      By.css('mat-drawer[data-mat-drawer-top-open]')
-    )
-  }
-
-  async _getSideNavPrimaryExpanded(){
-    return (await this._getSideNavPrimary()
-      .getAttribute('data-mat-drawer-top-open')) === 'true'
-  }
-
-  _getSideNavSecondary(){
-    return this._browser.findElement(
-      By.css('mat-drawer[data-mat-drawer-fullleft-open]')
-    )
-  }
-
-  async _getSideNavSecondaryExpanded(){
-    return (await this._getSideNavSecondary()
-      .getAttribute('data-mat-drawer-fullleft-open')) === 'true'
-  }
-
-  async _setSideNavPrimaryExpanded(flag) {
-    const openedFlag = await this._getSideNavPrimaryExpanded()
-    if (typeof flag === 'undefined' || flag !== openedFlag) {
-      await this._browser.findElement(By.css(`button[aria-label="${ARIA_LABELS.TOGGLE_SIDE_PANEL}"]`)).click()
-    }
-  }
-
-  async getSideNavTag(){
-    return await this._browser
-      .findElement( By.css('[mat-drawer-trigger]') )
-      .findElement( By.css('i') )
-  }
-
-  sideNavIsVisible(){
-    throw new Error(`sideNavIsVisible is deprecated`)
-  }
-
-  _getSideNavTab(){
-    return this._browser
-      .findElement( By.css('[mat-drawer-trigger]') )
-      .findElement( By.css('i') )
-  }
-
-  sideNavTabIsVisible(){
-    return this._getSideNavTab().isDisplayed()
-  }
-
-  clickSideNavTab(){
-    return this._getSideNavTab().click()
-  }
-
-  /**
-   * StatusPanel
-   */
-  _getStatusPanel(){
-    return this._browser.findElement( By.css('[mat-drawer-status-panel]') )
-  }
-
-  async statusPanelIsVisible() {
-    try {
-      return await this._getStatusPanel().isDisplayed()
-    } catch (e) {
-      return false
-    }
-  }
-
-  clickStatusPanel() {
-    // Will throw if status panel is not visible
-    return this._getStatusPanel().click()
-  }
-
-  // will throw if additional layer control is not visible
-  additionalLayerControlIsExpanded() {
-    throw new Error(`additionalLayerControlIsExpanded is deprecated`)
-  }
-
-  /**
-   * TODO? deprecate
-   */
-  async toggleNthLayerControl(idx) {
-    const els = await this._browser
-      .findElement(
-        By.css(`[aria-label="${ARIA_LABELS.ADDITIONAL_VOLUME_CONTROL}"]`)
-      )
-      .findElements( By.css(`[aria-label="${ARIA_LABELS.TOGGLE_SHOW_LAYER_CONTROL}"]`))
-    if (!els[idx]) throw new Error(`toggleNthLayerControl index out of bound: accessor ${idx} with length ${els.length}`)
-    await els[idx].click()
-  }
-
-  // Signin banner
-  _getToolsIcon(){
-    return this._driver
-      .findElement( By.css('[aria-label="Show tools and plugins"]') )
-  }
-
-  async showToolsMenu(){
-    await this._getToolsIcon().click()
-  }
-
-  _getToolsMenu(){
-    return this._driver
-      .findElement( By.css('[aria-label="Tools and plugins menu"]') )
-  }
-
-  _getAllTools(){
-    return this._getToolsMenu().findElements( By.css('[role="menuitem"]') )
-  }
-
-  async getVisibleTools(){
-    // may throw if tools menu not visible
-    const menuItems = await this._getAllTools()
-    const returnArr = []
-    for (const menuItem of menuItems){
-      returnArr.push(
-        await _getTextFromWebElement(menuItem)
-      )
-    }
-    return returnArr
-  }
-
-  async clickOnNthTool(index, cssSelector){
-    const menuItems = await this._getAllTools()
-    if (!menuItems[index]) throw new Error(`index out of bound: accessing index ${index} of length ${menuItems.length}`)
-    if (cssSelector) await menuItems[index].findElement( By.css(cssSelector) ).click()
-    else await menuItems[index].click()
-  }
-
-  _getFavDatasetIcon(){
-    return this._driver
-      .findElement( By.css('[aria-label="Show pinned datasets"]') )
-  }
-
-  async showPinnedDatasetPanel(){
-    await this._getFavDatasetIcon().click()
-    await this.wait(500)
-  }
-
-  _getPinnedDatasetPanel(){
-    return this._driver
-      .findElement(
-        By.css('[aria-label="Pinned datasets panel"]')
-      )
-  }
-
-  async getPinnedDatasetsFromOpenedPanel(){
-    const list = await this._getPinnedDatasetPanel()
-      .findElements(
-        By.tagName('mat-list-item')
-      )
-
-    const returnArr = []
-    for (const el of list) {
-      const text = await _getTextFromWebElement(el)
-      returnArr.push(text)
-    }
-    return returnArr
-  }
-
-  async unpinNthDatasetFromOpenedPanel(index){
-    const list = await this._getPinnedDatasetPanel()
-      .findElements(
-        By.tagName('mat-list-item')
-      )
-
-    if (!list[index]) throw new Error(`index out of bound: ${index} in list with size ${list.length}`)
-    await list[index]
-      .findElement( By.css('[aria-label="Toggle pinning this dataset"]') )
-      .click()
-  }
-
-  _getWidgetPanel(title){
-    return this._driver.findElement( By.css(`[aria-label="Widget for ${title}"]`) )
-  }
-
-  async widgetPanelIsDispalyed(title){
-    try {
-      const isDisplayed = await this._getWidgetPanel(title).isDisplayed()
-      return isDisplayed
-    } catch (e) {
-      console.warn(`widgetPanelIsDisplayed error`, e)
-      return false
-    }
-  }
-
-  async closeWidgetByname(title){
-    await this._getWidgetPanel(title)
-      .findElement( By.css(`[aria-label="close"]`) )
-      .click()
-  }
-}
-
-module.exports = {
-  WdLayoutPage,
-  WdBase,
-}
\ No newline at end of file
diff --git a/e2e/util/selenium/util.js b/e2e/util/selenium/util.js
deleted file mode 100644
index 07aadf6a27365d35aa076a368b12e66583c6d760..0000000000000000000000000000000000000000
--- a/e2e/util/selenium/util.js
+++ /dev/null
@@ -1,25 +0,0 @@
-
-function _getTextFromWebElement(webElement) {
-  return webElement.getText()
-}
-
-async function _getIndexFromArrayOfWebElements(search, webElements) {
-  const texts = await Promise.all(
-    webElements.map(_getTextFromWebElement)
-  )
-  return texts.findIndex(text => search instanceof RegExp
-      ? search.test(text)
-      : text.indexOf(search) >= 0)
-}
-
-function _compareText(textString, testStrRegExp){
-  return testStrRegExp instanceof RegExp
-    ? testStrRegExp.test(textString)
-    : textString.indexOf(testStrRegExp) >= 0
-}
-
-module.exports = {
-  _getTextFromWebElement,
-  _getIndexFromArrayOfWebElements,
-  _compareText
-}
\ No newline at end of file
diff --git a/features/_convert.py b/features/_convert.py
index ecd36cac48cae44824bf21a6b990ffb5ae94eb3b..8b22a9e06c2f19b6afb30d27da8bc42cfbe16146 100644
--- a/features/_convert.py
+++ b/features/_convert.py
@@ -101,7 +101,7 @@ def gherkin_to_markdown(gherkin_text):
     )
 
 
-def main(output: str="./e2e/checklist.md"):
+def main(output: str="./checklist.md"):
     
     path_to_feature = Path("features")
     markdown_txt = """# Staging Checklist
diff --git a/mkdocs.yml b/mkdocs.yml
index dfd714d8026d57c4f6afbcb0ecc131a6a720663f..d1561a7764aef3917555ae88ffb04c9c3ffb6e44 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -45,6 +45,7 @@ nav:
     - Differential gene expression analysis: "advanced/differential_gene_expression_analysis.md"
 
   - Release notes:
+    - v2.14.7: 'releases/v2.14.7.md'
     - v2.14.6: 'releases/v2.14.6.md'
     - v2.14.5: 'releases/v2.14.5.md'
     - v2.14.4: 'releases/v2.14.4.md'
diff --git a/package-lock.json b/package-lock.json
index 01873b6c7ddecd1bbe5a1fcf921258e0d1dd944d..1f5725874bc3a1d6f01a7865f2270ff31ab25d3e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
 {
   "name": "siibra-explorer",
-  "version": "2.14.5",
+  "version": "2.14.6",
   "lockfileVersion": 3,
   "requires": true,
   "packages": {
     "": {
       "name": "siibra-explorer",
-      "version": "2.14.5",
+      "version": "2.14.6",
       "license": "apache-2.0",
       "dependencies": {
         "@angular/animations": "^15.2.10",
@@ -23,7 +23,7 @@
         "@ngrx/effects": "^15.4.0",
         "@ngrx/store": "^15.4.0",
         "acorn": "^8.4.1",
-        "export-nehuba": "^0.1.8",
+        "export-nehuba": "^0.1.9",
         "file-loader": "^6.2.0",
         "jszip": "^3.6.0",
         "postcss": "^8.3.6",
@@ -7646,9 +7646,9 @@
       "dev": true
     },
     "node_modules/export-nehuba": {
-      "version": "0.1.8",
-      "resolved": "https://registry.npmjs.org/export-nehuba/-/export-nehuba-0.1.8.tgz",
-      "integrity": "sha512-A5RijEUDqhv09yAOeVb2AxS36YmJNyWXRmcImPFSGgLq9bP8bcjrHIbmBOsEX9ntAKwwaHNvlVVmDSwHnGqFug==",
+      "version": "0.1.9",
+      "resolved": "https://registry.npmjs.org/export-nehuba/-/export-nehuba-0.1.9.tgz",
+      "integrity": "sha512-59vm+BlB1zuD2ftDWUGUv6Jt0WGHjzB6egGGuD+JRR9oW4D7m9DNuOwheymSvlUxJ2GEOjMBe3I460T51m6W/A==",
       "dependencies": {
         "pako": "^1.0.6"
       }
diff --git a/package.json b/package.json
index dfe5f4708b9d5482f9bcd70604ef75eb7bc75b6c..4654168aff06b996f84488df25690b5c3223feab 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "siibra-explorer",
-  "version": "2.14.6",
+  "version": "2.14.7",
   "description": "siibra-explorer - explore brain atlases. Based on humanbrainproject/nehuba & google/neuroglancer. Built with angular",
   "scripts": {
     "lint": "eslint src --ext .ts",
@@ -12,10 +12,7 @@
     "test": "ng test",
     "test-ci": "ng test --progress false --watch false --browsers=ChromeHeadless",
     "sapi-schema": "curl 'https://siibra-api-stable.apps.hbp.eu/v3_0/openapi.json' | jq > ./src/atlasComponents/sapi/openapi.json && npx openapi-typescript@6.1.0 ./src/atlasComponents/sapi/openapi.json --output ./src/atlasComponents/sapi/schemaV3.ts && eslint ./src/atlasComponents/sapi/schemaV3.ts --no-ignore --fix",
-    "api-schema": "node src/api/generateSchema.mjs",
-    "docs:json": "compodoc -p ./tsconfig.json -e json -d .",
-    "storybook": "npm run docs:json && start-storybook -p 6006",
-    "build-storybook": "npm run docs:json && build-storybook"
+    "api-schema": "node src/api/generateSchema.mjs"
   },
   "keywords": [],
   "author": "FZJ-INM1-BDA <inm1-bda@fz-juelich.de>",
@@ -55,7 +52,7 @@
     "@ngrx/effects": "^15.4.0",
     "@ngrx/store": "^15.4.0",
     "acorn": "^8.4.1",
-    "export-nehuba": "^0.1.8",
+    "export-nehuba": "^0.1.9",
     "file-loader": "^6.2.0",
     "jszip": "^3.6.0",
     "postcss": "^8.3.6",
diff --git a/src/index.html b/src/index.html
index 95d9da0bf8f5a092b4ac37a3aa42cc3a5ffb4596..89bed597be4739486f6374d6a5a365a3630021a4 100644
--- a/src/index.html
+++ b/src/index.html
@@ -16,6 +16,7 @@
   <script type="module" src="https://unpkg.com/ng-layer-tune@0.0.26/dist/ng-layer-tune/ng-layer-tune.esm.js"></script>
   <script type="module" src="https://unpkg.com/hbp-connectivity-component@0.6.6/dist/connectivity-component/connectivity-component.js" ></script>
   <script src="https://cdn.plot.ly/plotly-2.24.1.min.js" charset="utf-8"></script>
+  <script src="main.bundle.js" charset="utf-8"></script> <!-- export_nehuba -->
   <title>Siibra Explorer</title>
 </head>
 <body>
diff --git a/src/ui/ui.module.ts b/src/ui/ui.module.ts
index 98efd3854b801b7cffe5d1720ffc32fab5ea32d7..dbacdadf9c546f69ffacf94b45c1b5dd8abbefb5 100644
--- a/src/ui/ui.module.ts
+++ b/src/ui/ui.module.ts
@@ -9,8 +9,6 @@ import { UtilModule } from "src/util";
 import { ShareModule } from "src/share";
 import { AuthModule } from "src/auth";
 import { ActionDialog } from "./actionDialog/actionDialog.component";
-import { APPEND_SCRIPT_TOKEN, appendScriptFactory } from "src/util/constants";
-import { DOCUMENT } from "@angular/common";
 import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
 import { HANDLE_SCREENSHOT_PROMISE, TypeHandleScrnShotPromise } from "../screenshot";
 
@@ -32,11 +30,6 @@ import { HANDLE_SCREENSHOT_PROMISE, TypeHandleScrnShotPromise } from "../screens
     ActionDialog,
   ],
   providers: [
-    {
-      provide: APPEND_SCRIPT_TOKEN,
-      useFactory: appendScriptFactory,
-      deps: [DOCUMENT]
-    },
     {
       provide: HANDLE_SCREENSHOT_PROMISE,
       useValue: ((param) => {
diff --git a/src/viewerModule/nehuba/module.ts b/src/viewerModule/nehuba/module.ts
index 76b1be3db1e3a5046702286313b63e6e6ebe3edc..d6d5906e9741ddfbf7a469e2eecbd82a49f8b629 100644
--- a/src/viewerModule/nehuba/module.ts
+++ b/src/viewerModule/nehuba/module.ts
@@ -1,9 +1,8 @@
 import { APP_INITIALIZER, NgModule } from "@angular/core";
 import { NehubaViewerContainerDirective } from './nehubaViewerInterface/nehubaViewerInterface.directive'
-import { IMPORT_NEHUBA_INJECT_TOKEN, NehubaViewerUnit } from "./nehubaViewer/nehubaViewer.component";
+import { NehubaViewerUnit } from "./nehubaViewer/nehubaViewer.component";
 import { CommonModule } from "@angular/common";
-import { APPEND_SCRIPT_TOKEN } from "src/util/constants";
-import { importNehubaFactory, NEHUBA_INSTANCE_INJTKN } from "./util";
+import { NEHUBA_INSTANCE_INJTKN } from "./util";
 import { NehubaViewerTouchDirective } from "./nehubaViewerInterface/nehubaViewerTouch.directive";
 import { StoreModule } from "@ngrx/store";
 import { NEHUBA_VIEWER_FEATURE_KEY } from "./constants";
@@ -18,7 +17,7 @@ import { FormsModule, ReactiveFormsModule } from "@angular/forms";
 import { BehaviorSubject } from "rxjs";
 import { StateModule } from "src/state";
 import { AuthModule } from "src/auth";
-import {QuickTourModule} from "src/ui/quickTour/module";
+import { QuickTourModule } from "src/ui/quickTour/module";
 import { WindowResizeModule } from "src/util/windowResize";
 import { EffectsModule } from "@ngrx/effects";
 import { MeshEffects } from "./mesh.effects/mesh.effects";
@@ -81,12 +80,6 @@ import { MediaQueryDirective } from "src/util/directives/mediaQuery.directive";
     StatusCardComponent,
   ],
   providers: [
-    
-    {
-      provide: IMPORT_NEHUBA_INJECT_TOKEN,
-      useFactory: importNehubaFactory,
-      deps: [ APPEND_SCRIPT_TOKEN ]
-    },
     {
       provide: NEHUBA_INSTANCE_INJTKN,
       useValue: new BehaviorSubject(null)
diff --git a/src/viewerModule/nehuba/nehubaViewer/nehubaViewer.component.spec.ts b/src/viewerModule/nehuba/nehubaViewer/nehubaViewer.component.spec.ts
index 89b3a42f99d93c8222d314784bfa9b6057de5aa1..bee657a551771449ef3fca3599aea69be8983412 100644
--- a/src/viewerModule/nehuba/nehubaViewer/nehubaViewer.component.spec.ts
+++ b/src/viewerModule/nehuba/nehubaViewer/nehubaViewer.component.spec.ts
@@ -1,6 +1,6 @@
 import { TestBed, fakeAsync, tick, ComponentFixture } from "@angular/core/testing"
 import { CommonModule } from "@angular/common"
-import { NehubaViewerUnit, IMPORT_NEHUBA_INJECT_TOKEN, scanFn } from "./nehubaViewer.component"
+import { NehubaViewerUnit, scanFn } from "./nehubaViewer.component"
 import { LoggingModule, LoggingService } from "src/logging"
 import { IMeshesToLoad, SET_MESHES_TO_LOAD } from "../constants"
 import { Subject } from "rxjs"
@@ -90,10 +90,6 @@ describe('> nehubaViewer.component.ts', () => {
           NehubaViewerUnit
         ],
         providers:[
-          {
-            provide: IMPORT_NEHUBA_INJECT_TOKEN,
-            useValue: () => Promise.resolve(),
-          },
           {
             provide: SET_MESHES_TO_LOAD,
             useFactory: () => setMeshToLoadCtl$
diff --git a/src/viewerModule/nehuba/nehubaViewer/nehubaViewer.component.ts b/src/viewerModule/nehuba/nehubaViewer/nehubaViewer.component.ts
index 6e2f8251fa76b4d8910b3d3f7d012542a95024fb..99ec8489b9f043e862a3caf14c751df95227d859 100644
--- a/src/viewerModule/nehuba/nehubaViewer/nehubaViewer.component.ts
+++ b/src/viewerModule/nehuba/nehubaViewer/nehubaViewer.component.ts
@@ -24,7 +24,6 @@ function translateUnit(unit: Unit) {
   throw new Error(`Cannot translate unit: ${unit}`)
 }
 
-export const IMPORT_NEHUBA_INJECT_TOKEN = `IMPORT_NEHUBA_INJECT_TOKEN`
 
 interface LayerLabelIndex {
   layer: {
@@ -123,7 +122,6 @@ export class NehubaViewerUnit implements OnDestroy {
     public elementRef: ElementRef,
     private log: LoggingService,
     private periodicSvc: PeriodicSvc,
-    @Inject(IMPORT_NEHUBA_INJECT_TOKEN) getImportNehubaPr: () => Promise<any>,
     @Optional() @Inject(NEHUBA_INSTANCE_INJTKN) private nehubaViewer$: Subject<NehubaViewerUnit>,
     @Optional() @Inject(SET_MESHES_TO_LOAD) private injSetMeshesToLoad$: Observable<IMeshesToLoad>,
     @Optional() @Inject(SET_COLORMAP_OBS) private setColormap$: Observable<IColorMap>,
@@ -194,8 +192,7 @@ export class NehubaViewerUnit implements OnDestroy {
       this.nehubaViewer$.next(this)
     }
 
-    getImportNehubaPr()
-      .then(() => getExportNehuba())
+    getExportNehuba()
       .then(exportNehuba => {
         this.nehubaLoaded = true
         this.exportNehuba = exportNehuba
@@ -417,9 +414,7 @@ export class NehubaViewerUnit implements OnDestroy {
       this.log.error(err)
     });
 
-    (window as any).nehubaViewer = this.nehubaViewer
-
-    const viewer = window['viewer']
+    const viewer = this.nehubaViewer.ngviewer
 
     /**
      * Hide all layers except the base layer (template)
diff --git a/src/viewerModule/nehuba/util.ts b/src/viewerModule/nehuba/util.ts
index 0af076efd9c18e061e1e9f539c2911445aae4c77..8091d50beb6b4974bf7afe4d1eccc6b1d6a30d14 100644
--- a/src/viewerModule/nehuba/util.ts
+++ b/src/viewerModule/nehuba/util.ts
@@ -178,18 +178,6 @@ export const isIdentityQuat = (ori: number[]): boolean => Math.abs(ori[0]) < 1e-
   && Math.abs(ori[2]) < 1e-6
   && Math.abs(ori[3] - 1) < 1e-6
 
-export const importNehubaFactory = (appendSrc: (src: string) => Promise<void>): () => Promise<void> => {
-  let pr: Promise<void>
-  return async () => {
-    if (!!(window as any).export_nehuba) return 
-
-    if (pr) return pr
-    pr = appendSrc('main.bundle.js')
-
-    return pr
-  }
-}
-
 export const takeOnePipe = () => {
 
   return pipe(