diff --git a/.github/workflows/docker_img.yml b/.github/workflows/docker_img.yml
index 76e8788819f6139821b2794a5452ae25ee55d7fe..928c13769d4d699156888a04ee5cad19f0519a1b 100644
--- a/.github/workflows/docker_img.yml
+++ b/.github/workflows/docker_img.yml
@@ -6,16 +6,16 @@ jobs:
   build-docker-img:
     runs-on: ubuntu-latest
     env:
-      MATOMO_ID_DEV: '7'
-      MATOMO_URL_DEV: 'https://stats-dev.humanbrainproject.eu/'
       MATOMO_ID_PROD: '12'
       MATOMO_URL_PROD: 'https://stats.humanbrainproject.eu/'
       PRODUCTION: 'true'
       DOCKER_REGISTRY: 'docker-registry.ebrains.eu/siibra/'
+
       SIIBRA_API_STABLE: 'https://siibra-api-stable.apps.hbp.eu/v1_0'
       SIIBRA_API_RC: 'https://siibra-api-rc.apps.hbp.eu/v1_0'
       SIIBRA_API_LATEST: 'https://siibra-api-latest.apps-dev.hbp.eu/v1_0'
 
+
     steps:
     - uses: actions/checkout@v2
     - name: 'Set matomo env var'
@@ -57,6 +57,7 @@ jobs:
           VERSION=$(git rev-parse --short HEAD)
           echo "EXPERIMENTAL_FEATURE_FLAG=true" >> $GITHUB_ENV
         fi
+        echo "Setting VERSION: $VERSION"
         echo "VERSION=$VERSION" >> $GITHUB_ENV
     - name: 'Build docker image'
       run: |
@@ -88,7 +89,8 @@ jobs:
     runs-on: ubuntu-latest
     env:
       GITHUB_API_ROOT: https://api.github.com/repos/fzj-inm1-bda/siibra-explorer
-      
+      OC_TEMPLATE_NAME: 'siibra-explorer-branch-deploy-2'
+
     needs: build-docker-img
     steps:
       - uses: actions/checkout@v2
@@ -112,13 +114,13 @@ jobs:
             echo "OKD_URL=https://okd.hbp.eu:443" >> $GITHUB_ENV
             echo "OKD_SECRET=${{ secrets.OKD_PROD_SECRET }}" >> $GITHUB_ENV
             echo "OKD_PROJECT=interactive-viewer" >> $GITHUB_ENV
-            echo "PATH_POSTFIX=" >> $GITHUB_ENV
+            echo "ROUTE_HOST=siibra-explorer.apps.hbp.eu" >> $GITHUB_ENV
             echo "Deploy on prod cluster..."
           else
             echo "OKD_URL=https://okd-dev.hbp.eu:443" >> $GITHUB_ENV
             echo "OKD_SECRET=${{ secrets.OKD_DEV_SECRET }}" >> $GITHUB_ENV
             echo "OKD_PROJECT=interactive-atlas-viewer" >> $GITHUB_ENV
-            echo "PATH_POSTFIX=-dev" >> $GITHUB_ENV
+            echo "ROUTE_HOST=siibra-explorer.apps-dev.hbp.eu" >> $GITHUB_ENV
             echo "BUILD_TEXT=$BRANCH_NAME" >> $GITHUB_ENV
             echo "Deploy on dev cluster..."
           fi
@@ -127,39 +129,35 @@ jobs:
           oc login $OKD_URL --token=$OKD_SECRET
           oc project $OKD_PROJECT
 
-          # sanitized branchname == remove _ / and lowercase everything
-          SANITIZED_BRANCH_NAME=$(echo ${BRANCH_NAME//[_\/]/} | awk '{ print tolower($0) }')
-          echo "SANITIZED_BRANCH_NAME=$SANITIZED_BRANCH_NAME" >> $GITHUB_ENV
-          echo "Working branch name: $BRANCH_NAME, sanitized branch name: $SANITIZED_BRANCH_NAME"
+          # DEPLOY_ID == remove _ / and lowercase everything from branch
+          DEPLOY_ID=$(echo ${BRANCH_NAME//[_\/]/} | awk '{ print tolower($0) }')
+          echo "DEPLOY_ID=$DEPLOY_ID" >> $GITHUB_ENV
+          
+          ROUTE_PATH=/$DEPLOY_ID
+          echo "ROUTE_PATH=$ROUTE_PATH" >> $GITHUB_ENV
+
+          echo "Working branch name: $BRANCH_NAME, deploy_id: $DEPLOY_ID"
 
           # check if the deploy already exist
-          if oc get dc siibra-explorer-branch-deploy-$SANITIZED_BRANCH_NAME; then
+          if oc get dc ${{ env.OC_TEMPLATE_NAME }}-$DEPLOY_ID; then
             # trigger redeploy if deployconfig exists already
-            echo "dc siibra-explorer-branch-deploy-$SANITIZED_BRANCH_NAME already exist, redeploy..."
-            oc rollout latest dc/siibra-explorer-branch-deploy-$SANITIZED_BRANCH_NAME
+            echo "dc ${{ env.OC_TEMPLATE_NAME }}-$DEPLOY_ID already exist, redeploy..."
+            oc rollout latest dc/${{ env.OC_TEMPLATE_NAME }}-$DEPLOY_ID
           else 
             # create new app if deployconfig does not yet exist
-            echo "dc siibra-explorer-branch-deploy-$SANITIZED_BRANCH_NAME does not yet exist, create new app..."
-            oc new-app --template siibra-explorer-branch-deploy \
+            echo "dc ${{ env.OC_TEMPLATE_NAME }}-$DEPLOY_ID does not yet exist, create new app..."
+            oc new-app --template ${{ env.OC_TEMPLATE_NAME }} \
               -p BRANCH_NAME=$BRANCH_NAME \
-              -p SANITIZED_BRANCH_NAME=$SANITIZED_BRANCH_NAME \
-              -p PATH_POSTFIX=$PATH_POSTFIX \
+              -p DEPLOY_ID=$DEPLOY_ID \
+              -p ROUTE_HOST=$ROUTE_HOST \
+              -p ROUTE_PATH=$ROUTE_PATH \
               -p BUILD_TEXT=$BUILD_TEXT
           fi
       - name: 'Update status badge'
         if: success()
         run: |
 
-          if [[ "$GITHUB_REF" == 'refs/heads/master' ]]
-          then
-            DEPLOY_URL="https://siibra-explorer.apps.hbp.eu/master"
-          elif [[ "$GITHUB_REF" == 'refs/heads/staging' ]]
-          then
-            DEPLOY_URL="https://siibra-explorer.apps.hbp.eu/staging"
-          else
-            DEPLOY_URL="https://siibra-explorer.apps-dev.hbp.eu/${{ env.SANITIZED_BRANCH_NAME }}"
-          fi
-
+          DEPLOY_URL=https://$ROUTE_HOST$ROUTE_PATH
           curl -v \
             -X POST \
             -H "authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
@@ -168,5 +166,7 @@ jobs:
             -d '{
               "target_url":"'$DEPLOY_URL'",
               "name": "Deployed at OKD",
+              "description": "Deployed at OKD",
+              "context": "[ebrains-okd-deploy] Deployed at OKD",
               "state": "success"
             }'
diff --git a/.github/workflows/manual_e2e.yml b/.github/workflows/manual_e2e.yml
index 27877ea0cb6cb3167b8a8bc3833c392d63e02c14..9829d7053bd047b73209192c0effbb5c87715599 100644
--- a/.github/workflows/manual_e2e.yml
+++ b/.github/workflows/manual_e2e.yml
@@ -24,8 +24,6 @@ jobs:
 
     steps:
     - uses: actions/checkout@v2
-      with:
-        ref: 'master'
     - name: 'Add checklist comment'
       uses: actions/github-script@v5
       with:
diff --git a/.github/workflows/on_branch_del.yml b/.github/workflows/on_branch_del.yml
index bb83d05f8023646dd7e6794346c3bc858aa23e44..03bb4f463498bcfe5de32a41892604912c54974a 100644
--- a/.github/workflows/on_branch_del.yml
+++ b/.github/workflows/on_branch_del.yml
@@ -10,6 +10,8 @@ on:
 jobs:
   remove-deploy:
     runs-on: ubuntu-latest
+    env:
+      OC_TEMPLATE_NAME: 'siibra-explorer-branch-deploy-2'
     steps:
     - name: 'Set env var'
       run: |
@@ -26,14 +28,12 @@ jobs:
         oc login $OKD_URL --token=$OKD_SECRET
         oc project $OKD_PROJECT
         # sanitized branchname == remove _ / and lowercase everything
-        SANITIZED_BRANCH_NAME=$(echo ${BRANCH_NAME//[_\/]/} | awk '{ print tolower($0) }')
-        echo "SANITIZED_BRANCH_NAME=$SANITIZED_BRANCH_NAME" >> $GITHUB_ENV
-        echo "Working branch name: $BRANCH_NAME, sanitized branch name: $SANITIZED_BRANCH_NAME"
+        DEPLOY_ID=$(echo ${BRANCH_NAME//[_\/]/} | awk '{ print tolower($0) }')
+        echo "DEPLOY_ID=$DEPLOY_ID" >> $GITHUB_ENV
+        echo "Working branch name: $BRANCH_NAME, sanitized branch name: $DEPLOY_ID"
     - name: 'List and delete all labelled resoures'
       run: |
         oc get all \
-          -l template=siibra-explorer-branch-deploy-template \
-          -l app=siibra-explorer-branch-deploy-$SANITIZED_BRANCH_NAME
+          -l app=${{ env.OC_TEMPLATE_NAME }}-$DEPLOY_ID
         oc delete all \
-          -l template=siibra-explorer-branch-deploy-template \
-          -l app=siibra-explorer-branch-deploy-$SANITIZED_BRANCH_NAME
+          -l app=${{ env.OC_TEMPLATE_NAME }}-$DEPLOY_ID
diff --git a/.openshift/README.md b/.openshift/v1/README.v1.md
similarity index 98%
rename from .openshift/README.md
rename to .openshift/v1/README.v1.md
index db1f804c7db0affbedcc01c271f015893c51fa20..7be9e08e08289363b9cb34c5fcf46f5769b8cc51 100644
--- a/.openshift/README.md
+++ b/.openshift/v1/README.v1.md
@@ -143,7 +143,6 @@ Per [deployment template](./okd-branch-tmpl.yaml), a number of parameters may be
 | name | required | desc | 
 | --- | --- | --- |
 | `SESSION_SECRET` | | Random strings to encrypt sessions. Not currently used. |
-| `DOCKER_IMAGE_TAG` | true | Dictates which image tag to pull. Currently, possible values are `{latest\|rc\|stable}`. |
 | `BRANCH_NAME` | true | Determines the tag of the image to pull. |
 | `SANITIZED_BRANCH_NAME` | true | Strip all special characters from `BRANCH_NAME`. Acts similar to deploy ID. Distinguishes one deployment from another. Also affects routes: `siibra-explorer-{SANITIZED_BRANCH_NAME}.apps{PATH_POSTFIX}.hbp.eu` |
 | `PATH_POSTFIX` | | Dictates if postfix, if any, should be added to the route: `siibra-explorer-{DEPLOY_FLAVOUR}.apps{PATH_POSTFIX}.hbp.eu`. Defaults to `''` (empty string). Possible value: `-dev`|
diff --git a/.openshift/okd_branch_tmpl.yaml b/.openshift/v1/okd_branch_tmpl_v1.yaml
similarity index 100%
rename from .openshift/okd_branch_tmpl.yaml
rename to .openshift/v1/okd_branch_tmpl_v1.yaml
diff --git a/.openshift/v2/README.v2.md b/.openshift/v2/README.v2.md
new file mode 100644
index 0000000000000000000000000000000000000000..902bfd83fd171eff1881e8bde58849dca4c8a470
--- /dev/null
+++ b/.openshift/v2/README.v2.md
@@ -0,0 +1,150 @@
+# Deployment documentation
+
+This document outlines the deployment of `siibra-explorer` on EBRAINS infrastructure.
+
+## Overview
+
+`siibra-explorer` are continuously deployed on openshift container platform hosted by EBRAINS.
+
+The continuous deployment of `siibra-explorer` involves the following steps:
+
+- building docker image
+- tag the image, and push to registry
+- pull and run the newly built image
+
+## Build
+
+This section outlines the procedure of continuously building and archiving docker images of `siibra-explorer`.
+
+### Images
+
+Docker images are built with [`Dockerfile`](../Dockerfile) by github action withs [yml spec](../.github/workflows/docker_img.yml), and pushed to EBRAINS docker image registry at `docker-registry.ebrains.eu`
+
+`docker-registry.ebrains.eu` is set as the registry
+
+`siibra` is set as the namespace
+
+`siibra-explorer` is set as the image name
+
+The built image will be tagged with the branch name. e.g.
+
+`docker-registry.ebrains.eu/siibra/siibra-explorer:{BRANCH_NAME}`
+
+### Registry
+
+The built docker image will then be pushed to `docker-registry.ebrains.eu` with the access token of a bot account with the rights to push image in `siibra` namespace.
+
+The login credentials are stored in github action secrets:
+
+- username: `{{ secrets.EBRAINS_DOCKER_REG_USER }}`
+- access token: `{{ secrets.EBRAINS_DOCKER_REG_TOKEN }}`
+
+> :warning: There are currently no mechanism to delete artefacts from `docker-registry.ebrains.eu`. One must periodically, manually delete untagged images to avoid filling of allotted diskspace.
+
+---
+
+// TODO setup retention policy to allow automatic deletion of artefacts
+
+---
+
+## Deployment
+
+This section outlines how the built image are deployed.
+
+> :information_source: Previous internal guides described a combination of s2i with docker build strategy. This has been demonstrated to be both slow (at build time) and unreliable (over the deployment lifetime).
+
+### Variables
+
+| cluster   | name           | value | 
+| ---       | ---            | --- |
+| prod      | `PROJECT_NAME` | `interactive-viewer` |
+|           | `OKD_ENDPOINT` | `https://okd.hbp.eu:443` |
+|           | `OKD_SECRET`   | `{{ secrets.OKD_PROD_SECRET }}` (generated once[1] stored in github action secrets) |
+| dev       | `PROJECT_NAME` | `interactive-viewer` |
+|           | `OKD_ENDPOINT` | `https://okd-dev.hbp.eu:443` |
+|           | `OKD_SECRET`   | `{{ secrets.OKD_DEV_SECRET }}` (generated once[1], stored in github action secrets) |
+
+
+### Triggering deployment
+
+Deployments resides in [docker-img.yml](../.github/workflows/docker_img.yml), `job['trigger-deploy']`. The steps are summarised as below:
+
+- determine if targeting prod or dev cluster.
+
+  - If the trigger is update of `master` or `staging` branch, target prod cluster
+
+  - Anyother branch, target dev cluster
+
+- login to openshift container platform with the command
+
+  ```bash
+  oc login ${OKD_ENDPOINT} --token ${OKD_SECRET}
+  ```
+
+- checkout project with the command
+
+  ```bash
+  oc project ${PROJECT_NAME}
+  ```
+
+- check if deployment with name `siibra-explorer-branch-deploy-${SANITIZED_BRANCH_NAME}` exists
+  - if exists, rollout latest deployment with the command 
+  
+    ```bash
+    oc rollout latest dc/siibra-explorer-branch-deploy-${SANITIZED_BRANCH_NAME}
+    ```
+
+  - if does not exist, create new deployment with name `siibra-explorer-branch-deploy-${SANITIZED_BRANCH_NAME}`, using deployment template[2] with corresponding parameters[3]
+
+### [1] OKD service accounts
+
+In order to deploy on OKD clusters in CI/CD pipeline, it is ideal to create a service account. Openshift container platform maintains [a comprehensive guide](https://docs.openshift.com/container-platform/3.11/dev_guide/service_accounts.html) on service account. This section provides a step by step guide on creating the service account.
+
+> :information_source: Why not just use personal access token? 1/ it expires, 2/ it is invalidated when you logout, 3/ (to a less degree, since personal access token has a expiration), revoking personal access token has a greater impact on developer experience, and potentially breaks more things, if one reuses the same personally access token.
+
+#### Prereq
+
+- openshift cli installed (check via `which oc`)
+- login command (easiest method to obtain login command: login via web portal > portrait username (*top right*) > Copy Login Command )
+
+#### Configure a Service Account
+
+- login via terminal (paste login command from prereq)
+- select the desired project via `oc project ${PROJECT_NAME}`
+- create a new SA via: `oc create sa ${SERVICE_ACCOUNT_NAME}`
+- get a new token via: `oc sa get-token ${SERVICE_ACCOUNT_NAME}` (store this token securely, ideally in a password manager)
+- grant the SA ability to create deployments via: `oc policy add-role-to-user edit -z ${SERVICE_ACCOUNT_NAME}`
+
+
+### [2] Deployment template
+
+An [openshift template](./okd-branch-tmpl.yaml) has been added to both production (https://okd.hbp.eu) and develop (https://okd-dev.hbp.eu) clusters.
+
+This is done ahead of any deploys, is valid for all future deploys and rarely needs to be updated.
+
+> :warning: The process of editing template is fragile and error prone. One should be vigilant and update the template as little as possible. Ideally, add new templates and alter the deployment pipeline, rather than edit existing templates.
+
+The template is produced mainly by referencing Openshift container platform [template API](https://docs.openshift.com/container-platform/3.11/rest_api/template_openshift_io/template-template-openshift-io-v1.html).
+
+A number of sensitive variables are stored on the openshift clusters, and added to the container at runtime. They include:
+
+| variable name | from | description |
+| --- | --- | --- |
+| `REDIS_PASSWORD` | `okd_secret.redis-rate-limiting-db-ephemeral.database-password` | password to redis |
+| `*` | `okd_configmap.hbp-oauth-config-map.*` | Contains Client ID, Client secret etc for oauth with EBRAINS IAM service |
+| `*` | `okd_configmap.fluent-logging.*` | Contains fluentd logging variables |
+| `*` | `okd_configmap.plugins.*` | Contains plugins variables |
+| `*` | `okd_configmap.other-deploy-config.*` | Contains other deploy variables |
+
+### [3] Deployment parameters
+
+Per [deployment template](./okd-branch-tmpl.yaml), a number of parameters may be required when creating new deployments.
+
+| name | required | desc | 
+| --- | --- | --- |
+| `SESSION_SECRET` | | Random strings to encrypt sessions. Not currently used. |
+| `BRANCH_NAME` | true | Determines the tag of the image to pull. |
+| `ROUTE_HOST` | true | host field of route service of the deployed template. Possible values are `*.apps.hbp.eu` for prod, `*.apps-dev.hbp.eu` for dev. Must **not** end with `/` |
+| `ROUTE_PATH` | | path field of route service of the deployed template. If set, **must** start with `/`  |
+| `DEPLOY_ID` | true | Strip all special characters from `BRANCH_NAME`. Distinguishes one deployment from another. |
+| `BUILD_TEXT` | | Shows as over lay text, to mark dev build. Defaults to `dev build` |
\ No newline at end of file
diff --git a/.openshift/v2/okd_branch_tmpl_v2.yaml b/.openshift/v2/okd_branch_tmpl_v2.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..3c95ec2f701e87531bb089d0c7e47c1bc020a08a
--- /dev/null
+++ b/.openshift/v2/okd_branch_tmpl_v2.yaml
@@ -0,0 +1,144 @@
+apiVersion: v1
+kind: Template
+metadata:
+  name: siibra-explorer-branch-deploy-2
+  annotations:
+    description: "Deploy branch of siibra-explorer"
+    tags: "nodejs,siibra-explorer"
+objects:
+- apiVersion: v1
+  kind: DeploymentConfig
+  metadata:
+    name: siibra-explorer-branch-deploy-2-${DEPLOY_ID}
+    labels:
+      app: siibra-explorer-branch-deploy-2-${DEPLOY_ID}
+  spec:
+    replicas: 3
+    revisionHistoryLimit: 10
+    selector:
+      deploymentconfig: siibra-explorer-branch-deploy-2-${DEPLOY_ID}
+    template:
+      metadata:
+        labels:
+          app: siibra-explorer-branch-deploy
+          deploymentconfig: siibra-explorer-branch-deploy-2-${DEPLOY_ID}
+      spec:
+          containers:
+          - env:
+            - name: SESSION_SECRET
+              value: ${SESSION_SECRET}
+            - name: HOSTNAME
+              value: https://${ROUTE_HOST}
+            - name: HOST_PATHNAME
+              value: ${ROUTE_PATH}
+              
+            - name: BUILD_TEXT
+              value: ${BUILD_TEXT}
+            - name: REDIS_PASSWORD
+              valueFrom:
+                secretKeyRef:
+                  key: database-password
+                  name: redis-rate-limiting-db-ephemeral
+            envFrom:
+            - configMapRef:
+                name: hbp-oauth-config-map
+            - configMapRef:
+                name: fluent-logging
+            - configMapRef:
+                name: plugins
+            - configMapRef:
+                name: other-deploy-config
+
+            image: "docker-registry.ebrains.eu/siibra/siibra-explorer:${BRANCH_NAME}"
+            imagePullPolicy: Always
+            livenessProbe:
+              failureThreshold: 3
+              httpGet:
+                path: ${ROUTE_PATH}/ready
+                port: 8080
+                scheme: HTTP
+              initialDelaySeconds: 10
+              periodSeconds: 10
+              successThreshold: 1
+              timeoutSeconds: 1
+            readinessProbe:
+              failureThreshold: 3
+              httpGet:
+                path: ${ROUTE_PATH}/ready
+                port: 8080
+                scheme: HTTP
+              initialDelaySeconds: 3
+              periodSeconds: 10
+              successThreshold: 1
+              timeoutSeconds: 6
+            name: siibra-explorer-2-${DEPLOY_ID}
+            ports:
+            - containerPort: 8080
+              protocol: TCP
+            resources: {}
+            terminationMessagePath: /dev/termination-log
+            terminationMessagePolicy: File
+          dnsPolicy: ClusterFirst
+          restartPolicy: Always
+          schedulerName: default-scheduler
+          securityContext: {}
+          terminationGracePeriodSeconds: 30
+- apiVersion: v1
+  kind: Service
+  metadata:
+    labels:
+      app: siibra-explorer-branch-deploy-2-${DEPLOY_ID}
+    name: siibra-explorer-branch-deploy-2-${DEPLOY_ID}
+  spec:
+    ports:
+    - name: 8080-tcp
+      port: 8080
+      protocol: TCP
+      targetPort: 8080
+    selector:
+      deploymentconfig: siibra-explorer-branch-deploy-2-${DEPLOY_ID}
+    type: ClusterIP
+- apiVersion: v1
+  kind: Route
+  metadata:
+    labels:
+      app: siibra-explorer-branch-deploy-2-${DEPLOY_ID}
+    name: siibra-explorer-branch-deploy-2-${DEPLOY_ID}
+  spec:
+    host: ${ROUTE_HOST}
+    path: ${ROUTE_PATH}
+    port:
+      targetPort: 8080-tcp
+    tls:
+      insecureEdgeTerminationPolicy: Redirect
+      termination: edge
+    to:
+      kind: Service
+      name: siibra-explorer-branch-deploy-2-${DEPLOY_ID}
+      weight: 100
+    wildcardPolicy: None
+
+parameters:
+- description: Session secret
+  from: '[A-Z0-9]{16}'
+  generate: expression
+  name: SESSION_SECRET
+
+- name: BRANCH_NAME
+  required: true
+- name: DEPLOY_ID
+  required: true
+  description: |
+    ID that distinguish deployments.
+    Use only [a-z0-9]{4,}
+- name: ROUTE_HOST
+  description: route/host for the deployed service. Must be unique, or route may not be deployed. Must **NOT** end with with /.
+  required: true
+- name: ROUTE_PATH
+  description: path for the deployed service. May be left empty. If set, must start with /.
+  value: ''
+- name: BUILD_TEXT
+  description: 'UI displaying which build'
+  value: 'dev build'
+labels:
+  template: siibra-explorer-branch-deploy-template-v2
diff --git a/common/util.spec.js b/common/util.spec.js
index a66f12a39bd1307fbc17573f078937e37d742350..2af63766c202999af0a9ca2ccf57a341d947f0ee 100644
--- a/common/util.spec.js
+++ b/common/util.spec.js
@@ -1,4 +1,4 @@
-import { getIdFromFullId, strToRgb } from './util'
+import { getIdFromFullId, strToRgb, verifyPositionArg } from './util'
 
 describe('common/util.js', () => {
   describe('getIdFromFullId', () => {
@@ -76,4 +76,45 @@ describe('common/util.js', () => {
     })
   
   })
+
+  describe('verifyPositionArg', () => {
+    describe('malformed input', () => {
+      let input
+      it('> if props.components[0] is string', () => {
+        input= 'hello world'
+        expect(verifyPositionArg(input)).toBeFalsy()
+      })
+      it('> if position property is object', () => {
+        input={
+          x: 0,
+          y: 0,
+          z: 0
+        }
+        expect(verifyPositionArg(input)).toBeFalsy()
+      })
+
+      it('> if position property is array of incorrect length', () => {
+        input=[]
+        expect(verifyPositionArg(input)).toBeFalsy()
+      })
+
+      it('> if position property is array contain non number elements', () => {
+        input = [1, 2, 'hello world']
+        expect(verifyPositionArg(input)).toBeFalsy()
+      })
+
+      it('> if position property is array contain NaN', () => {
+        input=[1,2,NaN]
+        expect(verifyPositionArg(input)).toBeFalsy()
+      })
+
+    })
+
+    describe('correct input', () => {
+      let input
+      it('> return true', () => {
+        expect(verifyPositionArg([1,2,3])).toBeTruthy()
+      })
+    })
+  })
 })
diff --git a/deploy/auth/util.js b/deploy/auth/util.js
index 4733f5070d9ef981d3ca4c9f6720834ae229f12b..91421d1624ad5d787a338cbdd7a497eba1a3be81 100644
--- a/deploy/auth/util.js
+++ b/deploy/auth/util.js
@@ -1,73 +1,5 @@
-const { configureAuth, jwtDecode } = require('./oidc')
 const objStoreDb = new Map()
 
-const HOSTNAME = process.env.HOSTNAME || 'http://localhost:3000'
-const HOST_PATHNAME = process.env.HOST_PATHNAME || ''
-const clientId = process.env.HBP_CLIENTID || 'no hbp id'
-const clientSecret = process.env.HBP_CLIENTSECRET || 'no hbp client secret'
-const discoveryUrl = 'https://services.humanbrainproject.eu/oidc'
-const redirectUri = `${HOSTNAME}${HOST_PATHNAME}/hbp-oidc/cb`
-
-let REFRESH_TOKEN = process.env.REFRESH_TOKEN || null
-const CLIENT_NOT_INIT = `Client is not initialised.`
-const REFRESH_TOKEN_MISSING = `refresh token is missing`
-const REFRESH_ACCESS_TOKEN_MISSING = `access token not defined upon refresh`
-const REFRESH_REFRESH_TOKEN_MISSING = `refresh token not defined upon refresh`
-
-let __client
-let __publicAccessToken
-
-const refreshToken = async () => {
-  if (!__client) throw new Error(CLIENT_NOT_INIT)
-  if (!REFRESH_TOKEN) throw new Error(REFRESH_TOKEN_MISSING)
-  const tokenset = await __client.refresh(REFRESH_TOKEN)
-  const {access_token: accessToken, refresh_token: refreshToken, id_token: idToken} = tokenset
-  if (!accessToken) throw new Error(REFRESH_ACCESS_TOKEN_MISSING)
-  if (!refreshToken) throw new Error(REFRESH_REFRESH_TOKEN_MISSING)
-  if (refreshToken !== REFRESH_TOKEN) {
-    REFRESH_TOKEN = refreshToken
-  }
-  __publicAccessToken = accessToken
-  return true
-}
-
-const getClient = async () => {
-  const { client } = await configureAuth({
-    clientId,
-    clientSecret,
-    discoveryUrl,
-    redirectUri,
-    clientConfig: {
-      redirect_uris: [ redirectUri ],
-      response_types: [ 'code' ]
-    }
-  })
-
-  __client = client
-}
-
-getClient()
-
-const getPublicAccessToken = async () => {
-  if (!__client) {
-    await getClient()
-  }
-  
-  if (!__publicAccessToken) {
-    await refreshToken()
-  }
-
-  const decoded = jwtDecode(__publicAccessToken)
-  const { exp } = decoded
-
-  // refresh token if it is less than 30 minute expiring
-  if (!exp || isNaN(exp) || (exp * 1000 - Date.now() < 1e3 * 60 * 30 )) {
-    await refreshToken()
-  }
-  
-  return __publicAccessToken
-}
-
 const initPassportJs = app => {
   console.log('init passport js')
   const passport = require('passport')
@@ -91,5 +23,4 @@ const initPassportJs = app => {
 module.exports = {
   initPassportJs,
   objStoreDb,
-  getPublicAccessToken: async () => await getPublicAccessToken(),
 }
diff --git a/deploy/auth/util.spec.js b/deploy/auth/util.spec.js
index 1d8a33ae229aa4540d80edb1fba201e80cdd9d97..0dff0d61ee3806108844187e81691a2396374864 100644
--- a/deploy/auth/util.spec.js
+++ b/deploy/auth/util.spec.js
@@ -113,43 +113,6 @@ describe('util.js', async () => {
       cleanup()
     })
 
-    it('> configureAuth and refresh called with correct param', async () => {
-      const { getPublicAccessToken } = require('./util')
-      const token = await getPublicAccessToken()
-
-      const {
-        access_token,
-        refresh_token,
-        id_token,
-        configureAuthStub,
-        refreshSpy,
-        jwtDecodeReturn,
-        jwtDecodeStub
-      } = oidcStub
-      const { HBP_CLIENTID, HBP_CLIENTSECRET, HOSTNAME, HOST_PATHNAME, REFRESH_TOKEN } = env
-      
-      // configuAuthStub
-      assert(
-        configureAuthStub.called,
-        'expect configureAuthStub to have been called once'
-      )
-      const { args } = configureAuthStub.firstCall
-      const arg = args[0]
-      expect(arg).to.include({
-        clientId: HBP_CLIENTID,
-        clientSecret: HBP_CLIENTSECRET,
-        redirectUri: `${HOSTNAME}${HOST_PATHNAME}/hbp-oidc/cb`
-      })
-
-      // refresh spy
-      assert(refreshSpy.calledWith(REFRESH_TOKEN))
-      
-      // jwtStub
-      assert(jwtDecodeStub.calledWith(access_token))
-
-      // return val
-      expect(token).to.be.equal(access_token)
-    })
   })
 
   describe('> if refresh token is missing', () => {
@@ -184,15 +147,5 @@ describe('util.js', async () => {
       cleanup()
     })
 
-    it('> refresh getPublicAccessToken will reject', async () => {
-      const { getPublicAccessToken } = require('./util')
-
-      try {
-        await getPublicAccessToken()
-        assert(false, 'get public access token should be rejected')
-      } catch (e) {
-        assert(true)
-      }
-    })
   })
 })
diff --git a/deploy/package-lock.json b/deploy/package-lock.json
index 99b93fe79026380a2f1ca7f051b65e97774a31f5..5d707a769ac807f9c1473f3940fe0464dba4657b 100644
--- a/deploy/package-lock.json
+++ b/deploy/package-lock.json
@@ -257,9 +257,9 @@
       },
       "dependencies": {
         "lodash": {
-          "version": "4.17.20",
-          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
-          "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA=="
+          "version": "4.17.21",
+          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+          "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
         }
       }
     },
@@ -735,9 +735,9 @@
       "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
     },
     "denque": {
-      "version": "1.5.0",
-      "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.0.tgz",
-      "integrity": "sha512-CYiCSgIF1p6EUByQPlGkKnP1M9g0ZV3qMIrqMqZqdwazygIA/YP2vrbcyl1h/WppKJTdl1F85cXIle+394iDAQ=="
+      "version": "1.5.1",
+      "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz",
+      "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw=="
     },
     "depd": {
       "version": "1.1.2",
@@ -1352,9 +1352,9 @@
       "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
     },
     "jose": {
-      "version": "2.0.4",
-      "resolved": "https://registry.npmjs.org/jose/-/jose-2.0.4.tgz",
-      "integrity": "sha512-EArN9f6aq1LT/fIGGsfghOnNXn4noD+3dG5lL/ljY3LcRjw1u9w+4ahu/4ahsN6N0kRLyyW6zqdoYk7LNx3+YQ==",
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/jose/-/jose-2.0.5.tgz",
+      "integrity": "sha512-BAiDNeDKTMgk4tvD0BbxJ8xHEHBZgpeRZ1zGPPsitSyMgjoMWiLGYAE7H7NpP5h0lPppQajQs871E8NHUrzVPA==",
       "requires": {
         "@panva/asn1.js": "^1.0.0"
       }
@@ -1446,9 +1446,9 @@
       }
     },
     "lodash": {
-      "version": "4.17.20",
-      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
-      "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==",
+      "version": "4.17.21",
+      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+      "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
       "dev": true
     },
     "lodash.defaults": {
@@ -1801,9 +1801,9 @@
       "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="
     },
     "normalize-url": {
-      "version": "4.5.0",
-      "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz",
-      "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ=="
+      "version": "4.5.1",
+      "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz",
+      "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA=="
     },
     "npm-run-path": {
       "version": "2.0.2",
@@ -2194,20 +2194,20 @@
       }
     },
     "redis": {
-      "version": "3.0.2",
-      "resolved": "https://registry.npmjs.org/redis/-/redis-3.0.2.tgz",
-      "integrity": "sha512-PNhLCrjU6vKVuMOyFu7oSP296mwBkcE6lrAjruBYG5LgdSqtRBoVQIylrMyVZD/lkF24RSNNatzvYag6HRBHjQ==",
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/redis/-/redis-3.1.2.tgz",
+      "integrity": "sha512-grn5KoZLr/qrRQVwoSkmzdbw6pwF+/rwODtrOr6vuBRiR/f3rjSTGupbF90Zpqm2oenix8Do6RV7pYEkGwlKkw==",
       "requires": {
-        "denque": "^1.4.1",
-        "redis-commands": "^1.5.0",
+        "denque": "^1.5.0",
+        "redis-commands": "^1.7.0",
         "redis-errors": "^1.2.0",
         "redis-parser": "^3.0.0"
       }
     },
     "redis-commands": {
-      "version": "1.6.0",
-      "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.6.0.tgz",
-      "integrity": "sha512-2jnZ0IkjZxvguITjFTrGiLyzQZcTvaw8DAaCXxZq/dsHXz7KfMQ3OUJy7Tz9vnRtZRVz6VRCPDvruvU8Ts44wQ=="
+      "version": "1.7.0",
+      "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.7.0.tgz",
+      "integrity": "sha512-nJWqw3bTFy21hX/CPKHth6sfhZbdiHP6bTawSgQBlKOVRG7EZkfHbbHwQJnrE4vsQf0CMNE+3gJ4Fmm16vdVlQ=="
     },
     "redis-errors": {
       "version": "1.2.0",
@@ -2819,9 +2819,9 @@
       "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
     },
     "y18n": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
-      "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w=="
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",
+      "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ=="
     },
     "yallist": {
       "version": "3.1.1",
diff --git a/deploy/package.json b/deploy/package.json
index 95da8df0bd39afe6c3076fe360260e3b4f81995b..8a165a87192525bf0b6bcd9ba86df86fe5ddb30c 100644
--- a/deploy/package.json
+++ b/deploy/package.json
@@ -26,7 +26,7 @@
     "nomiseco": "0.0.2",
     "openid-client": "^4.4.0",
     "passport": "^0.4.0",
-    "redis": "^3.0.2",
+    "redis": "^3.1.2",
     "request": "^2.88.0",
     "showdown": "^1.9.1",
     "soswrap": "^0.0.2",
diff --git a/deploy/saneUrl/index.js b/deploy/saneUrl/index.js
index d6d5caa2ab0ee69c8568a14ee02bd64bf2df7bbd..06659fa88748f40db5d57459c43c896b03e7babb 100644
--- a/deploy/saneUrl/index.js
+++ b/deploy/saneUrl/index.js
@@ -35,6 +35,11 @@ const getFile = async name => {
   return value
 }
 
+const hardCodedMap = new Map([
+  ['whs4', '#/a:minds:core:parcellationatlas:v1.0.0:522b368e-49a3-49fa-88d3-0870a307974a/t:minds:core:referencespace:v1.0.0:d5717c4a-0fa1-46e6-918c-b8003069ade8/p:minds:core:parcellationatlas:v1.0.0:ebb923ba-b4d5-4b82-8088-fa9215c2e1fe-v4/@:0.0.0.-W000.._eCwg.2-FUe3._-s_W.2_evlu..kxV..0.0.0..8Yu'],
+  ['mebrains', '#/a:juelich:iav:atlas:v1.0.0:monkey/t:minds:core:referencespace:v1.0.0:MEBRAINS_T1.masked/p:minds:core:parcellationatlas:v1.0.0:mebrains-tmp-id/@:0.0.0.-W000.._eCwg.2-FUe3._-s_W.2_evlu..7LIx..0.0.0..1LSm']
+])
+
 router.get('/:name', async (req, res) => {
   const { name } = req.params
   const { headers } = req
@@ -42,12 +47,19 @@ router.get('/:name', async (req, res) => {
   const redirectFlag = acceptHtmlProg.test(headers['accept'])
     
   try {
+    const REAL_HOSTNAME = `${HOSTNAME}${HOST_PATHNAME || ''}/`
+    const hardcodedRedir = hardCodedMap.get(name)
+    if (hardcodedRedir) {
+      if (redirectFlag) res.redirect(`${REAL_HOSTNAME}${hardcodedRedir}`)
+      else res.status(200).send(hardcodedRedir)
+      return
+    }
+
     const value = await getFile(name)
     if (!value) throw new NotFoundError()
     const json = JSON.parse(value)
     const { queryString } = json
 
-    const REAL_HOSTNAME = `${HOSTNAME}${HOST_PATHNAME || ''}/`
 
     if (redirectFlag) res.redirect(`${REAL_HOSTNAME}?${queryString}`)
     else res.status(200).send(value)
diff --git a/deploy/server.js b/deploy/server.js
index fdc0fbbbc27c19aafcdb0f989140bf5281000ba2..f628ffe7582de3f3d80178137634fd72885e2e40 100644
--- a/deploy/server.js
+++ b/deploy/server.js
@@ -7,9 +7,10 @@ if (process.env.NODE_ENV !== 'production') {
 
 if (process.env.FLUENT_HOST) {
   const Logger = require('./logging')
+  const os = require('os')
 
   const name = process.env.IAV_NAME || 'IAV'
-  const stage = process.env.IAV_STAGE || 'unnamed-stage'
+  const stage = os.hostname() || 'unknown-host'
 
   const protocol = process.env.FLUENT_PROTOCOL || 'http'
   const host = process.env.FLUENT_HOST || 'localhost'
diff --git a/deploy_env.md b/deploy_env.md
index ca6a5e72c6aa542a6b88471f88eb3174a3b2e05f..bb17c783cbd86d4fa1932a36f44f7a4118012452 100644
--- a/deploy_env.md
+++ b/deploy_env.md
@@ -47,7 +47,6 @@
 | `FLUENT_HOST` | host for fluent logging | `localhost` |
 | `FLUENT_PORT` | port for fluent logging | 24224 |
 | `IAV_NAME` | application name to be logged | `IAV` | 
-| `IAV_STAGE` | deploy of the application | `unnamed-stage` |
 
 ##### CSP
 
diff --git a/docs/releases/v2.5.4.md b/docs/releases/v2.5.4.md
new file mode 100644
index 0000000000000000000000000000000000000000..42cf2cb0441fe937427f4152b2a2636ef07d82e0
--- /dev/null
+++ b/docs/releases/v2.5.4.md
@@ -0,0 +1,13 @@
+# v2.5.4
+
+## Feature
+
+- Added MEBRAINS (Pre-release)
+
+## Under the hood
+
+- Added version check for siibra-api
+- Updated deploy template
+- Remove unused components
+- Clean up siibra-api types
+- temporarily added hardcoded redirects
diff --git a/e2e/checklist.md b/e2e/checklist.md
new file mode 100644
index 0000000000000000000000000000000000000000..7577819cb3cf150a1fc8588a165c9224b57290c0
--- /dev/null
+++ b/e2e/checklist.md
@@ -0,0 +1,51 @@
+# Staging Checklist
+
+**use incognito browser**
+
+[home page](https://siibra-explorer.apps.hbp.eu/staging/)
+
+## General
+
+- [ ] Can access front page
+- [ ] Can login to oidc v2 via top-right
+
+## Atlas data specific
+
+- [ ] Human multilevel atlas
+  - [ ] on click from home page, MNI152, Julich v2.9 loads without issue
+  - [ ] on hover, show correct region name(s)
+  - [ ] regional is fine :: select hOC1 right
+    - [ ] probabilistic map loads fine
+    - [ ] segmentation layer hides
+    - [ ] `navigate to` button exists, and works
+    - [ ] `Open in KG` button exists and works
+    - [ ] `Description` tabs exists and works
+    - [ ] `Regional features` tab exists and works
+      - [ ] `Receptor density` dataset exists and works
+        - [ ] `Open in KG` button exists and works
+        - [ ] `Preview` tab exists and works
+          - [ ] fingerprint is shown, interactable
+          - [ ] profiles can be loaded, interactable
+          - [ ] AR can be loaded
+      - [ ] `IEEG recordings` exists and works (at least 3)
+        - [ ] GDPR warning triangle
+        - [ ] `Open in KG` button exists and works
+        - [ ] perspective view works
+          - [ ] mesh becomes transparent
+          - [ ] mesh transparency returns when exit the panel
+          - [ ] electrodes appear in perspective view
+          - [ ] some contact points should apepar red (intersect with region)
+        - [ ] electrode tab
+          - [ ] show should a number of contact points
+          - [ ] clicking on electrode should navigate to the contact point location
+    - [ ] `Connectivity` tab exists and works
+      - [ ] on opening tab, PMap disappear, colour mapped segmentation appears
+      - [ ] on closing tab, PMap reappear, segmentation hides
+    - [ ] Explore in other templates exists, and has MNI152 and big brain
+      - [ ] clicking on the respective space will load julich 2.9 in that space
+      - [ ] the navigation should be preserved
+  - [ ] in big brain v2.9 (or latest)
+    - [ ] high res hoc1, hoc2, hoc3, lam1-6 are visible
+- [ ] Waxholm
+  - [ ] v4 are visible
+  - [ ] on hover, show correct region name(s)
\ No newline at end of file
diff --git a/mkdocs.yml b/mkdocs.yml
index 655bd195147c7e54c88e2e789c0ddfcfbcae5140..476dfab49e8293f4cb00942adf79868386926570 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -40,6 +40,7 @@ pages:
     - Fetching datasets: 'advanced/datasets.md'
     - Display non-atlas volumes: 'advanced/otherVolumes.md'
   - Release notes:
+    - v2.5.4: 'releases/v2.5.4.md'
     - v2.5.3: 'releases/v2.5.3.md'
     - v2.5.2: 'releases/v2.5.2.md'
     - v2.5.1: 'releases/v2.5.1.md'
diff --git a/package.json b/package.json
index 0212e036d37fdd03a9587ff2c4407639b4fc96e5..0f3aae01c1446f0e95a11d8265e25f925317d8d3 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "interactive-viewer",
-  "version": "2.5.3",
+  "version": "2.5.4",
   "description": "HBP interactive atlas viewer. Integrating KG query, dataset previews & more. Based on humanbrainproject/nehuba & google/neuroglancer. Built with angular",
   "scripts": {
     "build-aot": "VERSION=`node -e 'console.log(require(\"./package.json\").version)'` ng build && node ./third_party/matomo/processMatomo.js",
diff --git a/src/atlasComponents/parcellation/regionHierachy/regionHierarchy.style.css b/src/atlasComponents/parcellation/regionHierachy/regionHierarchy.style.css
index 6c0b05f0ebfe29bb0c3afef808d17fa7895000e0..480bb3e62be1e9d1014bccb4fca0c84340ef0401 100644
--- a/src/atlasComponents/parcellation/regionHierachy/regionHierarchy.style.css
+++ b/src/atlasComponents/parcellation/regionHierachy/regionHierarchy.style.css
@@ -58,16 +58,6 @@ input[type="text"]
   height:4rem;
 }
 
-.horizontal-mode .cdk-viewport-wrapper region-list-simple-view
-{
-  width: 200px;
-}
-
-.cdk-viewport-wrapper region-list-simple-view
-{
-  width: 100%;
-}
-
 .cdk-virtual-scroll-viewport-container.horizontal-mode
 {
   height: 6rem;
diff --git a/src/atlasComponents/parcellationRegion/index.ts b/src/atlasComponents/parcellationRegion/index.ts
index b3f4198bc8c372d02e1c43b01cd9809d18de3d1c..cced6b8edf56fd9c723124704267e3f5fd11e722 100644
--- a/src/atlasComponents/parcellationRegion/index.ts
+++ b/src/atlasComponents/parcellationRegion/index.ts
@@ -2,9 +2,7 @@ export {
   ParcellationRegionModule,
 } from "./module"
 
-
 export { RegionDirective } from "./region.directive";
-export { RegionListSimpleViewComponent } from "./regionListSimpleView/regionListSimpleView.component";
 export { RegionMenuComponent } from "./regionMenu/regionMenu.component";
 export { SimpleRegionComponent } from "./regionSimple/regionSimple.component";
 export { RenderViewOriginDatasetLabelPipe } from "./region.base";
\ No newline at end of file
diff --git a/src/atlasComponents/parcellationRegion/module.ts b/src/atlasComponents/parcellationRegion/module.ts
index fe7018e9efa9f3a7f2a54ed1cf8d99273e12cf77..d4507dcaa7e390cbeb96d0a1519c3070bb6ee1d8 100644
--- a/src/atlasComponents/parcellationRegion/module.ts
+++ b/src/atlasComponents/parcellationRegion/module.ts
@@ -5,7 +5,6 @@ import { AngularMaterialModule } from "src/sharedModules";
 import { UtilModule } from "src/util";
 import { RenderViewOriginDatasetLabelPipe } from "./region.base";
 import { RegionDirective } from "./region.directive";
-import { RegionListSimpleViewComponent } from "./regionListSimpleView/regionListSimpleView.component";
 import { RegionMenuComponent } from "./regionMenu/regionMenu.component";
 import { SimpleRegionComponent } from "./regionSimple/regionSimple.component";
 import { BSFeatureModule } from "../regionalFeatures/bsFeatures";
@@ -25,7 +24,6 @@ import { HttpClientModule } from "@angular/common/http";
   ],
   declarations: [
     RegionMenuComponent,
-    RegionListSimpleViewComponent,
     SimpleRegionComponent,
 
     RegionDirective,
@@ -34,7 +32,6 @@ import { HttpClientModule } from "@angular/common/http";
   ],
   exports: [
     RegionMenuComponent,
-    RegionListSimpleViewComponent,
     SimpleRegionComponent,
 
     RegionDirective,
diff --git a/src/atlasComponents/parcellationRegion/region.base.spec.ts b/src/atlasComponents/parcellationRegion/region.base.spec.ts
index ca0c1af0c60e78ba5802329c79a1a88588e92c17..df343917f7bb050a4a0b3553c1fabd7f918bfaa1 100644
--- a/src/atlasComponents/parcellationRegion/region.base.spec.ts
+++ b/src/atlasComponents/parcellationRegion/region.base.spec.ts
@@ -471,53 +471,51 @@ describe('> region.base.ts', () => {
       it('> does not populate if position property is absent', () => {
         regionBase.region = {
           ...mr0
-        }
+        } as any
         expect(regionBase.position).toBeFalsy()
       })
 
       describe('> does not populate if position property is malformed', () => {
-
-        it('> if position property is string', () => {
-          regionBase.region = {
-            ...mr0,
-            position: 'hello world'
-          }
+        it('> if region is falsy', () => {
+          regionBase.region = null
           expect(regionBase.position).toBeFalsy()
         })
-        it('> if position property is object', () => {
+        it('> if props is falsy', () => {
           regionBase.region = {
             ...mr0,
-            position: {
-              x: 0,
-              y: 0,
-              z: 0
-            }
-          }
+            props: null
+          } as any
           expect(regionBase.position).toBeFalsy()
         })
-
-        it('> if position property is array of incorrect length', () => {
+        it('> if props.components is falsy', () => {
           regionBase.region = {
             ...mr0,
-            position: []
-          }
+            props: {
+              components: null
+            }
+          } as any
           expect(regionBase.position).toBeFalsy()
         })
-
-        it('> if position property is array contain non number elements', () => {
+        it('> if props.components[0] is falsy', () => {
           regionBase.region = {
             ...mr0,
-            position: [1, 2, 'hello world']
-          }
+            props: {
+              components: []
+            }
+          } as any
           expect(regionBase.position).toBeFalsy()
         })
 
+        it('> if props.components[0].centroid is falsy', () => {
 
-        it('> if position property is array contain NaN', () => {
           regionBase.region = {
             ...mr0,
-            position: [1, 2, NaN]
-          }
+            props: {
+              components: [{
+                centroid: null
+              }]
+            }
+          } as any
           expect(regionBase.position).toBeFalsy()
         })
       })
@@ -525,8 +523,12 @@ describe('> region.base.ts', () => {
       it('> populates if position property is array with length 3 and non NaN element', () => {
         regionBase.region = {
           ...mr0,
-          position: [1, 2, 3]
-        }
+          props: {
+            components: [{
+              centroid: [1, 2, 3]
+            }]
+          },
+        } as any
         expect(regionBase.position).toBeTruthy()
       })
     })
@@ -549,7 +551,7 @@ describe('> region.base.ts', () => {
         const regionBase = new RegionBase(mockStore)
         regionBase.region = {
           rgb: [100, 120, 140]
-        }
+        } as any
         expect(
           regionBase.rgbString
         ).toEqual(`rgb(100,120,140)`)
@@ -560,7 +562,7 @@ describe('> region.base.ts', () => {
         const regionBase = new RegionBase(mockStore)
         regionBase.region = {
           labelIndex: 65535
-        }
+        } as any
         expect(
           regionBase.rgbString
         ).toEqual(`rgb(255,255,255)`)
@@ -576,7 +578,7 @@ describe('> region.base.ts', () => {
               ngId: 'foo',
               name: 'bar',
               labelIndex: 152
-            }
+            } as any
             expect(strToRgbSpy).toHaveBeenCalledWith(`foo152`)
           })
           it('> if ngId is not defined, use name', () => {
@@ -585,7 +587,7 @@ describe('> region.base.ts', () => {
             regionBase.region = {
               name: 'bar',
               labelIndex: 152
-            }
+            } as any
             expect(strToRgbSpy).toHaveBeenCalledWith(`bar152`)
           })
         })
@@ -601,7 +603,7 @@ describe('> region.base.ts', () => {
           const regionBase = new RegionBase(mockStore)
           regionBase.region = {
             foo: 'bar'
-          }
+          } as any
           expect(
             regionBase.rgbString
           ).toEqual(`rgb(${arr.join(',')})`)
@@ -613,7 +615,7 @@ describe('> region.base.ts', () => {
           const regionBase = new RegionBase(mockStore)
           regionBase.region = {
             foo: 'bar'
-          }
+          } as any
           expect(
             regionBase.rgbString
           ).toEqual(`rgb(255,200,200)`)
diff --git a/src/atlasComponents/parcellationRegion/region.base.ts b/src/atlasComponents/parcellationRegion/region.base.ts
index 31de7af98da5bcc6747b334f71787267b0240cf5..f596afe76f7cfbffc7e83a39c24993e0b52e7530 100644
--- a/src/atlasComponents/parcellationRegion/region.base.ts
+++ b/src/atlasComponents/parcellationRegion/region.base.ts
@@ -8,6 +8,8 @@ import { viewerStateSetConnectivityRegion, viewerStateNavigateToRegion, viewerSt
 import { viewerStateFetchedTemplatesSelector, viewerStateGetSelectedAtlas, viewerStateSelectedTemplateFullInfoSelector, viewerStateSelectedTemplateSelector } from "src/services/state/viewerState/selectors";
 import { strToRgb, verifyPositionArg, getRegionHemisphere } from 'common/util'
 import { getPosFromRegion } from "src/util/siibraApiConstants/fn";
+import { TRegionDetail } from "src/util/siibraApiConstants/types";
+import { IHasId } from "src/util/interfaces";
 
 @Directive()
 export class RegionBase {
@@ -15,7 +17,14 @@ export class RegionBase {
   public rgbString: string
   public rgbDarkmode: boolean
 
-  private _region: any
+  private _region: TRegionDetail & {  
+    context?: {
+      atlas: IHasId
+      template: IHasId
+      parcellation: IHasId
+    }
+    ngId?: string
+  }
 
   private _position: [number, number, number]
   set position(val){
@@ -34,16 +43,12 @@ export class RegionBase {
   set region(val) {
     this._region = val
     this.region$.next(this._region)
-    this.hasContext$.next(!!this._region.context)
+    this.hasContext$.next(!!this._region?.context)
 
     this.position = null
     // bug the centroid returned is currently nonsense
     // this.position = val?.props?.centroid_mm
     if (!this._region) return
-
-    if (val?.position) {
-      this.position = val?.position 
-    }
     const pos = getPosFromRegion(val)
     if (pos) {
       this.position = pos
@@ -65,7 +70,7 @@ export class RegionBase {
 
   get originDatainfos(){
     if (!this._region) return []
-    return this._region._dataset_specs || this._region.originDatainfos
+    return (this._region._dataset_specs || []).filter(spec => spec['@type'] === 'minds/core/dataset/v1.0.0')
   }
 
   public hasContext$: BehaviorSubject<boolean> = new BehaviorSubject(false)
diff --git a/src/atlasComponents/parcellationRegion/regionListSimpleView/regionListSimpleView.component.ts b/src/atlasComponents/parcellationRegion/regionListSimpleView/regionListSimpleView.component.ts
deleted file mode 100644
index 487d2bc7fd1867582acff52b44df985c46387f75..0000000000000000000000000000000000000000
--- a/src/atlasComponents/parcellationRegion/regionListSimpleView/regionListSimpleView.component.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-import { Component, Input } from "@angular/core";
-
-import { Store } from "@ngrx/store";
-import { IavRootStoreInterface } from "src/services/stateStore.service";
-import { RegionBase } from '../region.base'
-
-@Component({
-  selector: 'region-list-simple-view',
-  templateUrl: './regionListSimpleView.template.html',
-  styleUrls: [
-    './regionListSimpleView.style.css',
-  ],
-})
-
-export class RegionListSimpleViewComponent extends RegionBase {
-
-  @Input()
-  public showBrainIcon: boolean = false
-
-  @Input()
-  public showDesc: boolean = false
-
-  constructor(
-    store$: Store<IavRootStoreInterface>,
-  ) {
-    super(store$)
-  }
-}
diff --git a/src/atlasComponents/parcellationRegion/regionListSimpleView/regionListSimpleView.style.css b/src/atlasComponents/parcellationRegion/regionListSimpleView/regionListSimpleView.style.css
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/src/atlasComponents/parcellationRegion/regionListSimpleView/regionListSimpleView.template.html b/src/atlasComponents/parcellationRegion/regionListSimpleView/regionListSimpleView.template.html
deleted file mode 100644
index 1b4636a59534a5b5fd6cfe1269814e79ab520c2a..0000000000000000000000000000000000000000
--- a/src/atlasComponents/parcellationRegion/regionListSimpleView/regionListSimpleView.template.html
+++ /dev/null
@@ -1,29 +0,0 @@
-
-<!-- selected brain region -->
-<div class="flex-grow-1 flex-shrink-1 pt-2 pb-2 d-flex flex-row align-items-center flex-nowrap">
-  <i *ngIf="showBrainIcon" class="flex-grow-0 flex-shrink-0 fas fa-brain mr-2"></i>
-
-  <small class="flex-grow-1 flex-shrink-1 ">
-    {{ region.name }}
-  </small>
-
-  <button mat-icon-button
-    *ngIf="position"
-    class="flex-grow-0 flex-shrink-0"
-    (click)="navigateToRegion()" >
-    <i *ngIf="isSelected" class="fas fa-map-marked-alt"></i>
-  </button>
-
-  <button mat-icon-button
-    class="flex-grow-0 flex-shrink-0"
-    (click)="toggleRegionSelected()" >
-    <i *ngIf="isSelected" class="fas fa-trash"></i>
-    <i *ngIf="!isSelected" class="fas fa-plus"></i>
-  </button>
-</div>
-
-<mat-divider *ngIf="showDesc && region.description"></mat-divider>
-
-<small *ngIf="showDesc && region.description">
-  {{ region.description }}
-</small>
\ No newline at end of file
diff --git a/src/atlasComponents/parcellationRegion/regionMenu/regionMenu.template.html b/src/atlasComponents/parcellationRegion/regionMenu/regionMenu.template.html
index 1849ae9294154b0f4bf873f0af95c273a21de205..db607952a6369db63f42fc4bbf83d7d965c4d711 100644
--- a/src/atlasComponents/parcellationRegion/regionMenu/regionMenu.template.html
+++ b/src/atlasComponents/parcellationRegion/regionMenu/regionMenu.template.html
@@ -10,7 +10,6 @@
     <mat-card-title>
       <div class="position-relative region-name iv-custom-comp text">
         {{ region.name }}
-        <small *ngIf="region.status"> ({{region.status}})</small>
       </div>
     </mat-card-title>
 
@@ -22,20 +21,7 @@
       </span>
 
       <!-- origin datas format -->
-      <div *ngFor="let originDataset of (region.originDatasets || []); let index = index"
-        class="ml-2">
-        <i>&#183;</i>
-
-        <span *ngIf="originDataset?.format?.name as regionOrDsFormatName; else fallbackODsnameTmpl">
-          {{ regionOrDsFormatName }}
-        </span>
-        <ng-template #fallbackODsnameTmpl>
-          <span>
-            {{ regionOriginDatasetLabels$ | async | renderViewOriginDatasetlabel : index }}
-          </span>
-        </ng-template>
-      </div>
-
+      
       <mat-divider vertical="true" class="ml-2 h-2rem"></mat-divider>
 
       <!-- position -->
diff --git a/src/atlasComponents/parcellationRegion/regionSimple/regionSimple.template.html b/src/atlasComponents/parcellationRegion/regionSimple/regionSimple.template.html
index 7a8ce3161f2f78846774ca4f0da7f870bc458562..b724ab6f27d2ece74413959934d913d7b48888f5 100644
--- a/src/atlasComponents/parcellationRegion/regionSimple/regionSimple.template.html
+++ b/src/atlasComponents/parcellationRegion/regionSimple/regionSimple.template.html
@@ -1,7 +1,7 @@
 <div class="d-flex flex-row">
 
   <small class="text-truncate flex-shrink-1 flex-grow-1">
-    {{ region.name }}<span *ngIf="region.status" class="text-muted">{{' (' + region.status + ')'}}</span>
+    {{ region.name }}
   </small>
 
   <div class="flex-grow-0 flex-shrink-0 d-flex flex-row">
diff --git a/src/atlasComponents/regionalFeatures/bsFeatures/genericInfo/genericInfoCmp/genericInfo.component.ts b/src/atlasComponents/regionalFeatures/bsFeatures/genericInfo/genericInfoCmp/genericInfo.component.ts
index d36cc47d41c7edf1b4101c2544bc0913ccdcadf9..d3fcb22161ad3e74d66002f083f32c724f5224f1 100644
--- a/src/atlasComponents/regionalFeatures/bsFeatures/genericInfo/genericInfoCmp/genericInfo.component.ts
+++ b/src/atlasComponents/regionalFeatures/bsFeatures/genericInfo/genericInfoCmp/genericInfo.component.ts
@@ -5,14 +5,14 @@ import { ARIA_LABELS, CONST } from 'common/constants'
 import { TBSSummary } from "../../kgDataset";
 import { BsFeatureService } from "../../service";
 import { MAT_DIALOG_DATA } from "@angular/material/dialog";
-import { TDatainfos } from "src/util/siibraApiConstants/types";
+import { TDatainfosDetail } from "src/util/siibraApiConstants/types";
 import { TRegion } from "../../type";
 
 /**
  * this component is specifically used to render side panel ebrains dataset view
  */
 
-export type TInjectableData = TDatainfos & {
+export type TInjectableData = TDatainfosDetail & {
   dataType?: string
   view?: ViewRef | TemplateRef<any>
   region?: TRegion
diff --git a/src/atlasComponents/regionalFeatures/bsFeatures/kgDataset/showDataset/showDataset.directive.ts b/src/atlasComponents/regionalFeatures/bsFeatures/kgDataset/showDataset/showDataset.directive.ts
index 2cc1dae60470d227368d347a1dccda0b7529d124..5aeb3c1eb2310b954ae6346ca97fe78d67afeb85 100644
--- a/src/atlasComponents/regionalFeatures/bsFeatures/kgDataset/showDataset/showDataset.directive.ts
+++ b/src/atlasComponents/regionalFeatures/bsFeatures/kgDataset/showDataset/showDataset.directive.ts
@@ -2,7 +2,7 @@ import { Directive, HostListener, Inject, Input, Optional } from "@angular/core"
 import { MatDialog, MatDialogConfig } from "@angular/material/dialog";
 import { MatSnackBar } from "@angular/material/snack-bar";
 import { OVERWRITE_SHOW_DATASET_DIALOG_TOKEN, TOverwriteShowDatasetDialog } from "src/util/interfaces";
-import { TRegion as TSiibraRegion } from "src/util/siibraApiConstants/types";
+import { TRegionDetail as TSiibraRegion } from "src/util/siibraApiConstants/types";
 import { TRegion as TContextRegion } from 'src/atlasComponents/regionalFeatures/bsFeatures/type'
 
 export const IAV_DATASET_SHOW_DATASET_DIALOG_CMP = 'IAV_DATASET_SHOW_DATASET_DIALOG_CMP'
diff --git a/src/atlasViewer/atlasViewer.component.ts b/src/atlasViewer/atlasViewer.component.ts
index 18a1131c532fef980a53ce66a214e06e4fff844d..f866c771f21c42422f72bc7c32a9c9938146d7de 100644
--- a/src/atlasViewer/atlasViewer.component.ts
+++ b/src/atlasViewer/atlasViewer.component.ts
@@ -18,7 +18,6 @@ import {
   isDefined,
   safeFilter,
 } from "../services/stateStore.service";
-import { UNSUPPORTED_INTERVAL, UNSUPPORTED_PREVIEW } from "src/util/constants";
 import { WidgetServices } from "src/widget";
 
 import { LocalFileService } from "src/services/localFile.service";
@@ -31,7 +30,6 @@ import {MatSnackBar, MatSnackBarRef} from "@angular/material/snack-bar";
 import {MatDialog, MatDialogRef} from "@angular/material/dialog";
 import { ARIA_LABELS, CONST } from 'common/constants'
 
-import { MIN_REQ_EXPLAINER } from 'src/util/constants'
 import { SlServiceService } from "src/spotlight/sl-service.service";
 import { PureContantService } from "src/util";
 import { ClickInterceptorService } from "src/glue";
@@ -83,11 +81,6 @@ export class AtlasViewer implements OnDestroy, OnInit, AfterViewInit {
 
   private subscriptions: Subscription[] = []
 
-  public unsupportedPreviewIdx: number = 0
-  public unsupportedPreviews: any[] = UNSUPPORTED_PREVIEW
-
-  public MIN_REQ_EXPLAINER = MIN_REQ_EXPLAINER
-
   private selectedParcellation$: Observable<any>
   public selectedParcellation: any
 
@@ -173,23 +166,6 @@ export class AtlasViewer implements OnDestroy, OnInit, AfterViewInit {
       )
     }
 
-    if (!this.meetsRequirement) {
-      merge(
-        of(-1),
-        interval(UNSUPPORTED_INTERVAL),
-      ).pipe(
-        map(v => {
-          let idx = v
-          while (idx < 0) {
-            idx = v + this.unsupportedPreviews.length
-          }
-          return idx % this.unsupportedPreviews.length
-        }),
-      ).subscribe(val => {
-        this.unsupportedPreviewIdx = val
-      })
-    }
-
     this.subscriptions.push(
       this.pureConstantService.useTouchUI$.subscribe(bool => this.ismobile = bool),
     )
@@ -220,7 +196,7 @@ export class AtlasViewer implements OnDestroy, OnInit, AfterViewInit {
 
     this.subscriptions.push(
       this.pureConstantService.darktheme$.subscribe(flag => {
-        this.rd.setAttribute(document.body, 'darktheme', flag.toString())
+        this.rd.setAttribute(document.body, 'darktheme', this.meetsRequirement && flag.toString())
       }),
     )
   }
diff --git a/src/atlasViewer/atlasViewer.style.css b/src/atlasViewer/atlasViewer.style.css
index d89f76ce6b5edcc4463c44fd0c80db2465b002a8..c6c87ac87da646244f55ce6654b404763ee369c8 100644
--- a/src/atlasViewer/atlasViewer.style.css
+++ b/src/atlasViewer/atlasViewer.style.css
@@ -54,12 +54,6 @@ layout-floating-container > *
   max-width: 100%;
 }
 
-div[imageContainer]
-{
-  flex-grow: 1;
-  background: no-repeat center / contain;
-}
-
 div.displayCard
 {
   opacity: 0.8;
diff --git a/src/atlasViewer/atlasViewer.template.html b/src/atlasViewer/atlasViewer.template.html
index 01d2391c3916c8e6eeb1706c711aab6ee4df3825..fbaa8bf4c5dee3f37516c8d928c4c1a008897130 100644
--- a/src/atlasViewer/atlasViewer.template.html
+++ b/src/atlasViewer/atlasViewer.template.html
@@ -122,39 +122,7 @@
 
 <!-- does not meet req template -->
 <ng-template #doesNotMeetReqTemplate>
-  <div class="d-flex flex-column w-100 h-100" *ngIf="!meetsRequirement">
-    <div class="jumbotron bg-light text-center mb-0">
-      <div>
-        <h1 class="mb-3">
-          <i class="fas fa-exclamation-triangle"></i> Unsupported browser detected
-        </h1>
-        <p>
-          We recommend using the latest version of <a target="_blank" href="https://www.google.com/chrome/">Google
-            Chrome</a>
-          or <a target="_blank" href="https://www.mozilla.org/firefox/">Mozilla Firefox)</a> for viewing the interactive
-          viewer.
-        </p>
-        <div class="col-6 d-inline-block text-left">
-          <readmore-component [collapsedHeight]="0">
-            <markdown-dom [markdown]="MIN_REQ_EXPLAINER">
-
-            </markdown-dom>
-          </readmore-component>
-        </div>
-
-      </div>
-    </div>
-    <ng-container *ngFor="let preview of unsupportedPreviews; let idx = index">
-      <div [hidden]="idx !== unsupportedPreviewIdx" class="text-center mb-3" imageContainer
-        [style.backgroundImage]="'url(' + preview.previewSrc + ')'">
-        <div class="mt-2 card d-inline-block displayCard">
-          <div class="card-body">
-            {{ preview.text }}
-          </div>
-        </div>
-      </div>
-    </ng-container>
-  </div>
+  <not-supported-component></not-supported-component>
 </ng-template>
 
 <!-- logo tmpl -->
diff --git a/src/components/components.module.ts b/src/components/components.module.ts
index cf003404fd52616175b04be8cec8d85543d11c2f..1eafa1a3db4056567b6d554b6dbc1ffa65e89355 100644
--- a/src/components/components.module.ts
+++ b/src/components/components.module.ts
@@ -25,7 +25,6 @@ import { IAVVerticalButton } from './vButton/vButton.component';
 import { DynamicMaterialBtn } from './dynamicMaterialBtn/dynamicMaterialBtn.component';
 import { SpinnerCmp } from './spinner/spinner.component';
 import { ReadmoreModule } from './readmore';
-import { HoverableModule } from './hoverable';
 
 @NgModule({
   imports : [
@@ -36,7 +35,6 @@ import { HoverableModule } from './hoverable';
     AngularMaterialModule,
     UtilModule,
     ReadmoreModule,
-    HoverableModule,
   ],
   declarations : [
     /* components */
@@ -65,7 +63,6 @@ import { HoverableModule } from './hoverable';
   exports : [
     BrowserAnimationsModule,
     ReadmoreModule,
-    HoverableModule,
 
     MarkdownDom,
     TreeComponent,
diff --git a/src/components/hoverable/hoverableBlock.directive.ts b/src/components/hoverable/hoverableBlock.directive.ts
deleted file mode 100644
index 8868d046199d7706197fe7d31513f893e7b64b36..0000000000000000000000000000000000000000
--- a/src/components/hoverable/hoverableBlock.directive.ts
+++ /dev/null
@@ -1,70 +0,0 @@
-import { Directive, HostBinding, HostListener, Input, SecurityContext } from "@angular/core";
-import { DomSanitizer } from "@angular/platform-browser";
-
-@Directive({
-  selector : '[hoverable]',
-  host : {
-    style: `
-      transition :
-        opacity 0.3s ease,
-        box-shadow 0.3s ease,
-        transform 0.3s ease;
-      cursor : default;`,
-  },
-})
-
-export class HoverableBlockDirective {
-
-  @Input('hoverable')
-  public config: any = {
-    disable: false,
-    translateY: -5,
-  }
-
-  private _disable = false
-  private _translateY = -5
-
-  public ngOnChanges() {
-    this._disable = this.config && !!this.config.disable
-    /**
-     * 0 is evaluated as falsy, but a valid number
-     * conditional tests for whether we need to fall back to default
-     */
-    this._translateY = this.config && this.config.translateY !== 0 && !!Number(this.config.translateY)
-      ? Number(this.config.translateY)
-      : -5
-  }
-
-  @HostBinding('style.opacity')
-  public opacity: number = 0.9
-
-  @HostBinding('style.transform')
-  public transform = this.sanitizer.sanitize(SecurityContext.STYLE, `translateY(0px)`)
-
-  @HostBinding('style.box-shadow')
-  public boxShadow = this.sanitizer.sanitize(SecurityContext.STYLE, '0 4px 6px 0 rgba(5,5,5,0.1)')
-
-  @HostListener('mouseenter')
-  public onMouseenter() {
-    if (this._disable) { return }
-    this.opacity = 1.0
-    this.boxShadow = this.sanitizer.sanitize(SecurityContext.STYLE, `0 4px 6px 0 rgba(5,5,5,0.25)`)
-    /**
-     * n.b. risk of XSS. But sincle translate Y is passed through Number, and corerced into a number,
-     * and using 5 as a fallback, it should be safe
-     */
-    this.transform = this.sanitizer.sanitize(SecurityContext.STYLE, `translateY(${this._translateY}px)`)
-  }
-
-  @HostListener('mouseleave')
-  public onmouseleave() {
-    if (this._disable) { return }
-    this.opacity = 0.9
-    this.boxShadow = this.sanitizer.sanitize(SecurityContext.STYLE, `0 4px 6px 0 rgba(5,5,5,0.1)`)
-    this.transform = this.sanitizer.sanitize(SecurityContext.STYLE, `translateY(0px)`)
-  }
-
-  constructor(private sanitizer: DomSanitizer) {
-
-  }
-}
diff --git a/src/components/hoverable/index.ts b/src/components/hoverable/index.ts
deleted file mode 100644
index d0dc8b0c22be37dc381f8a507362cedc78f78370..0000000000000000000000000000000000000000
--- a/src/components/hoverable/index.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-export { HoverableModule } from './module'
-export { HoverableBlockDirective } from './hoverableBlock.directive'
\ No newline at end of file
diff --git a/src/components/hoverable/module.ts b/src/components/hoverable/module.ts
deleted file mode 100644
index 0913063fdfbe173b6b7b18637364f56373329c91..0000000000000000000000000000000000000000
--- a/src/components/hoverable/module.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import { CommonModule } from "@angular/common";
-import { NgModule } from "@angular/core";
-import { HoverableBlockDirective } from "./hoverableBlock.directive";
-
-@NgModule({
-  imports: [
-    CommonModule,
-  ],
-  declarations: [
-    HoverableBlockDirective,
-  ],
-  exports: [
-    HoverableBlockDirective
-  ]
-})
-
-export class HoverableModule{}
\ No newline at end of file
diff --git a/src/components/readmore/module.ts b/src/components/readmore/module.ts
index 255b721bcc67ce576a20103f7f8e13c87c387d39..ee0fb494d76221aea2171789c36c104eeb9325ef 100644
--- a/src/components/readmore/module.ts
+++ b/src/components/readmore/module.ts
@@ -1,14 +1,14 @@
 import { CommonModule } from "@angular/common";
 import { NgModule } from "@angular/core";
 import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
-import { HoverableModule } from "../hoverable";
+import { AngularMaterialModule } from "src/sharedModules";
 import { ReadmoreComponent } from "./readmoreCmp/readmore.component";
 
 @NgModule({
   imports: [
     CommonModule,
     BrowserAnimationsModule,
-    HoverableModule,
+    AngularMaterialModule,
   ],
   declarations: [
     ReadmoreComponent
diff --git a/src/components/readmore/readmoreCmp/readmore.component.ts b/src/components/readmore/readmoreCmp/readmore.component.ts
index ccbc0f773b993daaa1ed785b058d1177df5d0f76..914f7c09278b4953c8e24e67f9fe844db5fc38ce 100644
--- a/src/components/readmore/readmoreCmp/readmore.component.ts
+++ b/src/components/readmore/readmoreCmp/readmore.component.ts
@@ -14,7 +14,7 @@ export class ReadmoreComponent implements OnChanges, AfterContentChecked {
   @Input() public collapsedHeight: number = 45
   @Input() public show: boolean = false
   @Input() public animationLength: number = 180
-  @ViewChild('contentContainer') public contentContainer: ElementRef
+  @ViewChild('contentContainer', { read: ElementRef, static: true }) public contentContainer: ElementRef
 
   public fullHeight: number = 200
 
diff --git a/src/components/readmore/readmoreCmp/readmore.style.css b/src/components/readmore/readmoreCmp/readmore.style.css
index eda7922c5fa7532c99c4db4744aa95fd479c54af..166ec29d499bd01a7010e8753854ef89d1cfd161 100644
--- a/src/components/readmore/readmoreCmp/readmore.style.css
+++ b/src/components/readmore/readmoreCmp/readmore.style.css
@@ -1,12 +1,15 @@
-div.readmore-content
+:host
 {
-  overflow:hidden;
+  display: inline-block;
+  
+}
+
+.read-more-btn-container
+{
+  text-align: center;
 }
-div.readmore-sliver
+
+div.readmore-content
 {
-  width:100%;
-  display:flex;
-  flex-direction: column;
-  align-items: center;
-  background-color: rgba(128,128,128,0.1);
+  overflow:hidden;
 }
diff --git a/src/components/readmore/readmoreCmp/readmore.template.html b/src/components/readmore/readmoreCmp/readmore.template.html
index 2fa6c9975b6b2aa49712109c30512925157eebef..0eea38ac44faaa477c9757137a660c8804e3b5f4 100644
--- a/src/components/readmore/readmoreCmp/readmore.template.html
+++ b/src/components/readmore/readmoreCmp/readmore.template.html
@@ -1,18 +1,24 @@
-<div
-  [@collapseState] = "{ value : show ? 'visible' : 'collapsed', params : { collapsedHeight: collapsedHeight, fullHeight: fullHeight, animationLength: animationLength } }"
+<div [@collapseState] = "{
+    value: show
+      ? 'visible'
+      : 'collapsed',
+    params: {
+      collapsedHeight: collapsedHeight,
+      fullHeight: fullHeight,
+      animationLength: animationLength
+    }}"
   class="readmore-content">
   <div #contentContainer>
     <ng-content>
     </ng-content>
   </div>
 </div>
-<div 
-  (click)="toggle($event)" 
-  class="readmore-sliver"
-  [hoverable]="{translateY:-1}">
 
-  <i 
-    [ngClass] = "show ? 'fa-chevron-up' : 'fa-chevron-down'" 
-    class = "fas">
-  </i>
+<div class="read-more-btn-container">
+
+  <button mat-button (click)="toggle($event)" >
+    <i [ngClass] = "show ? 'fa-chevron-up' : 'fa-chevron-down'" 
+      class = "fas">
+    </i>
+  </button>
 </div>
\ No newline at end of file
diff --git a/src/main.module.ts b/src/main.module.ts
index 14806e6db813a562e356e7c6e94d47db01d499b5..ea82fa7eb23dbd27e2037f7f52ad1f3e7bdd43e1 100644
--- a/src/main.module.ts
+++ b/src/main.module.ts
@@ -57,6 +57,7 @@ import { of } from 'rxjs';
 import { GET_KGDS_PREVIEW_INFO_FROM_ID_FILENAME, OVERRIDE_IAV_DATASET_PREVIEW_DATASET_FN, kgTos, IAV_DATASET_PREVIEW_ACTIVE } from './databrowser.fallback'
 import { CANCELLABLE_DIALOG } from './util/interfaces';
 import { environment } from 'src/environments/environment' 
+import { NotSupportedCmp } from './notSupportedCmp/notSupported.component';
 
 export function debug(reducer: ActionReducer<any>): ActionReducer<any> {
   return function(state, action) {
@@ -123,6 +124,7 @@ export function debug(reducer: ActionReducer<any>): ActionReducer<any> {
   ],
   declarations : [
     AtlasViewer,
+    NotSupportedCmp,
     TryMeComponent,
 
     /* directives */
diff --git a/src/notSupportedCmp/notSupported.component.ts b/src/notSupportedCmp/notSupported.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..6562a46a650f2c2c8b01caa6b1fc174d7251157f
--- /dev/null
+++ b/src/notSupportedCmp/notSupported.component.ts
@@ -0,0 +1,35 @@
+import { Component } from "@angular/core";
+import { interval, merge, of } from "rxjs";
+import { map } from "rxjs/operators";
+import { UNSUPPORTED_INTERVAL, UNSUPPORTED_PREVIEW } from "src/util/constants";
+import { MIN_REQ_EXPLAINER } from 'src/util/constants'
+
+@Component({
+  selector: 'not-supported-component',
+  templateUrl: './notSupported.template.html',
+  styleUrls: [
+    './notSupported.style.css'
+  ]
+})
+
+export class NotSupportedCmp{
+  public unsupportedPreviews: any[] = UNSUPPORTED_PREVIEW
+  public unsupportedPreviewIdx: number = 0
+  public MIN_REQ_EXPLAINER = MIN_REQ_EXPLAINER
+  ngOnInit(){
+    merge(
+      of(-1),
+      interval(UNSUPPORTED_INTERVAL),
+    ).pipe(
+      map(v => {
+        let idx = v
+        while (idx < 0) {
+          idx = v + this.unsupportedPreviews.length
+        }
+        return idx % this.unsupportedPreviews.length
+      }),
+    ).subscribe(val => {
+      this.unsupportedPreviewIdx = val
+    })
+  }
+}
\ No newline at end of file
diff --git a/src/notSupportedCmp/notSupported.style.css b/src/notSupportedCmp/notSupported.style.css
new file mode 100644
index 0000000000000000000000000000000000000000..1d84ab645f8df54d59b8171693b704c6e2c5d87b
--- /dev/null
+++ b/src/notSupportedCmp/notSupported.style.css
@@ -0,0 +1,11 @@
+:host
+{
+  display: grid;
+  grid-template-rows: min-content 1fr;
+  height: 100%;
+}
+
+div.image-container
+{
+  background: no-repeat center / contain;
+}
diff --git a/src/notSupportedCmp/notSupported.template.html b/src/notSupportedCmp/notSupported.template.html
new file mode 100644
index 0000000000000000000000000000000000000000..3a6b141b3f74abca4a63153bd376439901a3cca1
--- /dev/null
+++ b/src/notSupportedCmp/notSupported.template.html
@@ -0,0 +1,31 @@
+<div class="jumbotron bg-light text-center mb-0">
+  <div>
+    <h1 class="mb-3">
+      <i class="fas fa-exclamation-triangle"></i> Unsupported browser detected
+    </h1>
+    <p>
+      We recommend using the latest version of <a target="_blank" href="https://www.google.com/chrome/">Google
+        Chrome</a>
+      or <a target="_blank" href="https://www.mozilla.org/firefox/">Mozilla Firefox)</a> for viewing the interactive
+      viewer.
+    </p>
+    <div class="col-6 d-inline-block text-left">
+      <readmore-component [collapsedHeight]="0">
+        <markdown-dom [markdown]="MIN_REQ_EXPLAINER">
+
+        </markdown-dom>
+      </readmore-component>
+    </div>
+
+  </div>
+</div>
+<ng-container *ngFor="let preview of unsupportedPreviews; let idx = index">
+  <div [hidden]="idx !== unsupportedPreviewIdx" class="text-center mb-3 image-container"
+    [style.backgroundImage]="'url(' + preview.previewSrc + ')'">
+    <div class="mt-2 card d-inline-block displayCard">
+      <div class="card-body">
+        {{ preview.text }}
+      </div>
+    </div>
+  </div>
+</ng-container>
\ No newline at end of file
diff --git a/src/routerModule/util.spec.ts b/src/routerModule/util.spec.ts
index ac15ff5981b022ed662be9c7796e07fff9e941a0..b2ed55ea82db7f09f581114c2157a40ad2731bb6 100644
--- a/src/routerModule/util.spec.ts
+++ b/src/routerModule/util.spec.ts
@@ -6,6 +6,8 @@ import { cvtFullRouteToState, cvtStateToHashedRoutes, DummyCmp, routes } from '.
 import { encodeNumber } from './cipher'
 import { Router } from '@angular/router'
 import { RouterTestingModule } from '@angular/router/testing'
+import * as parsedRoute from './parseRouteToTmplParcReg'
+import { spaceMiscInfoMap } from 'src/util/pureConstant.service'
 
 describe('> util.ts', () => {
   describe('> cvtFullRouteToState', () => {
@@ -61,6 +63,53 @@ describe('> util.ts', () => {
       })
     })
 
+    describe('> navigation', () => {
+      let parseSpy: jasmine.Spy
+      let mapGetSpy: jasmine.Spy
+      beforeEach(() => {
+        parseSpy = spyOnProperty(parsedRoute, 'parseSearchParamForTemplateParcellationRegion')
+        mapGetSpy = spyOn(spaceMiscInfoMap, 'get')
+      })
+      it('> if not present, should show something palatable', () => {
+        parseSpy.and.returnValue(() => ({
+          parcellationSelected: {
+            id: 'dummpy-id-parc'
+          },
+          regionsSelected: [],
+          templateSelected: {
+            id: 'dummpy-id-tmpl-sel'
+          },
+        }))
+
+        const scale = 0.25
+
+        mapGetSpy.and.returnValue({ scale })
+
+        const router = TestBed.inject(Router)
+        const route = `/a:juelich:iav:atlas:v1.0.0:1/t:minds:core:referencespace:v1.0.0:dafcffc5-4826-4bf1-8ff6-46b8a31ff8e2/p:minds:core:parcellationatlas:v1.0.0:94c1125b-b87e-45e4-901c-00daee7f2579-290`
+        const parsedUrl = router.parseUrl(route)
+        const { viewerState = {} } = cvtFullRouteToState(parsedUrl, {}) || {}
+        const { navigation } = viewerState
+        const {
+          orientation,
+          perspectiveOrientation,
+          position,
+          zoom,
+          perspectiveZoom,
+        } = navigation
+
+        expect(orientation).toEqual([0,0,0,1])
+        expect(perspectiveOrientation).toEqual([
+          0.3140767216682434,
+          -0.7418519854545593,
+          0.4988985061645508,
+          -0.3195493221282959
+        ])
+        expect(position).toEqual([0,0,0])
+        expect(zoom).toEqual(350000 * scale)
+        expect(perspectiveZoom).toEqual(1922235.5293810747 * scale)
+      })
+    })
   })
 
   describe('> cvtStateToHashedRoutes', () => {
diff --git a/src/routerModule/util.ts b/src/routerModule/util.ts
index 21ccdc6e7bbbb9bab69a399a96ac388d5fbc7439..bbf8791d3e53851ffb05a9e0acff9646003ff356 100644
--- a/src/routerModule/util.ts
+++ b/src/routerModule/util.ts
@@ -18,6 +18,7 @@ import {
   parseSearchParamForTemplateParcellationRegion,
   encodeId,
 } from './parseRouteToTmplParcReg'
+import { spaceMiscInfoMap } from "src/util/pureConstant.service"
 
 const endcodePath = (key: string, val: string|string[]) =>
   key[0] === '?'
@@ -34,6 +35,17 @@ const decodePath = (path: string) => {
   }
 }
 
+export const DEFAULT_NAV = {
+  orientation: [0, 0, 0, 1],
+  perspectiveOrientation: [
+    0.3140767216682434,
+    -0.7418519854545593,
+    0.4988985061645508,
+    -0.3195493221282959
+  ],
+  position: [0, 0, 0],
+}
+
 export const cvtFullRouteToState = (fullPath: UrlTree, state: any, _warnCb?: (arg: string) => void) => {
 
   const warnCb = _warnCb || ((...e: any[]) => console.warn(...e))
@@ -78,7 +90,7 @@ export const cvtFullRouteToState = (fullPath: UrlTree, state: any, _warnCb?: (ar
 
   // nav obj is almost always defined, regardless if standaloneVolume or not
   const cViewerState = returnObj['@'] && returnObj['@'][0]
-  let parsedNavObj = {}
+  let parsedNavObj: any
   if (cViewerState) {
     try {
       const [ cO, cPO, cPZ, cP, cZ ] = cViewerState.split(`${separator}${separator}`)
@@ -171,7 +183,14 @@ export const cvtFullRouteToState = (fullPath: UrlTree, state: any, _warnCb?: (ar
     returnState['viewerState']['regionsSelected'] = regionsSelected
     returnState['viewerState']['templateSelected'] = templateSelected
 
-    returnState['viewerState']['navigation'] = parsedNavObj
+    if (templateSelected) {
+      const { scale } = spaceMiscInfoMap.get(templateSelected.id) || { scale: 1 }
+      returnState['viewerState']['navigation'] = parsedNavObj || ({
+        ...DEFAULT_NAV,
+        zoom: 350000 * scale,
+        perspectiveZoom: 1922235.5293810747 * scale
+      })
+    }
   } catch (e) {
     // if error, show error on UI?
     warnCb(`parse template, parc, region error`, e)
diff --git a/src/services/state/ngViewerState.store.ts b/src/services/state/ngViewerState.store.ts
index f0ad5000d6b1e1e295f38c09a0749d30fdc9f03e..4b30e79372125b271161308125f9835400ec7886 100644
--- a/src/services/state/ngViewerState.store.ts
+++ b/src/services/state/ngViewerState.store.ts
@@ -14,6 +14,7 @@ import { generalApplyState } from '../stateStore.helper';
 import { ngViewerSelectorPanelMode, ngViewerSelectorPanelOrder } from './ngViewerState/selectors';
 import { uiActionSnackbarMessage } from './uiState/actions';
 import { TUserRouteError } from 'src/auth/auth.service';
+import { viewerStateSelectedTemplateSelector } from './viewerState.store.helper';
 
 export function mixNgLayers(oldLayers: INgLayerInterface[], newLayers: INgLayerInterface|INgLayerInterface[]): INgLayerInterface[] {
   if (newLayers instanceof Array) {
@@ -352,8 +353,8 @@ export class NgViewerUseEffect implements OnDestroy {
      * simplify with layer browser
      */
     const baseNgLayerName$ = this.store$.pipe(
-      select('viewerState'),
-      select('templateSelected'),
+      select(viewerStateSelectedTemplateSelector),
+      
       map(templateSelected => {
         if (!templateSelected) { return [] }
 
diff --git a/src/theme.scss b/src/theme.scss
index 5d8358d9b5f293359edd5bddb5fa63b09daab771..87c14ed3d10df20ac5ee476027f0071633be9ba2 100644
--- a/src/theme.scss
+++ b/src/theme.scss
@@ -71,15 +71,6 @@
     {
       color: mat.get-color-from-palette($warn, 500);
     }
-
-    &.hoverable
-    {
-      &:hover
-      {
-        // background-color: mat-color($background, hover);
-        cursor: pointer;
-      }
-    }
   }
 }
 
diff --git a/src/ui/logoContainer/logoContainer.style.css b/src/ui/logoContainer/logoContainer.style.css
index d36734ae3983a6fb3d974aef86ed828811f50b61..06a5526ebb72d220faddb2402cd0641d9327cb84 100644
--- a/src/ui/logoContainer/logoContainer.style.css
+++ b/src/ui/logoContainer/logoContainer.style.css
@@ -1,11 +1,11 @@
-[hbpLogoContainer]
+.hbpLogoContainer
 {
   display:inline-block;
   background-size: cover;
   height: 100%;
 }
 
-[hbpLogoContainer] > img
+.hbpLogoContainer > img
 {
   visibility: hidden;
   height: 100%;
diff --git a/src/ui/logoContainer/logoContainer.template.html b/src/ui/logoContainer/logoContainer.template.html
index 647ad7b86efe97d7edfdf11c293b32ce42b11049..989a828bec45e8d4f232c71c15b9322a3bd0c509 100644
--- a/src/ui/logoContainer/logoContainer.template.html
+++ b/src/ui/logoContainer/logoContainer.template.html
@@ -1,3 +1,3 @@
-<span [ngStyle]="containerStyle" hbpLogoContainer>
+<span [ngStyle]="containerStyle" class="hbpLogoContainer">
   <img [src]="imgSrc" />
 </span>
\ No newline at end of file
diff --git a/src/util/constants.ts b/src/util/constants.ts
index 03b462fb3e4573b084b2444b56805a3711e0d4e2..84ee596993c519223fc8f28487af1a0cb8372f4d 100644
--- a/src/util/constants.ts
+++ b/src/util/constants.ts
@@ -18,7 +18,7 @@ export const KG_TOS_VERSION = '0.3.0'
 export const DS_PREVIEW_URL = environment.DATASET_PREVIEW_URL
 export const BACKENDURL = (() => {
   const { BACKEND_URL } = environment
-  if (!BACKEND_URL) return `http://localhost:3000/`
+  if (!BACKEND_URL) return ``
   if (/^http/.test(BACKEND_URL)) return BACKEND_URL
 
   const url = new URL(window.location.href)
@@ -122,13 +122,13 @@ export const BS_ENDPOINT = new InjectionToken<string>('BS_ENDPOINT')
 
 export const UNSUPPORTED_PREVIEW = [{
   text: 'Preview of Colin 27 and JuBrain Cytoarchitectonic',
-  previewSrc: './res/image/1.png',
+  previewSrc: 'assets/images/1.png',
 }, {
   text: 'Preview of Big Brain 2015 Release',
-  previewSrc: './res/image/2.png',
+  previewSrc: 'assets/images/2.png',
 }, {
   text: 'Preview of Waxholm Rat V2.0',
-  previewSrc: './res/image/3.png',
+  previewSrc: 'assets/images/3.png',
 }]
 
 export const UNSUPPORTED_INTERVAL = 7000
diff --git a/src/util/interfaces.ts b/src/util/interfaces.ts
index a26040138cce0a2870743320d84ffaab500ab9d8..e5c2fbd9686a3f1036a5e34959c2e697e9f8d1a4 100644
--- a/src/util/interfaces.ts
+++ b/src/util/interfaces.ts
@@ -21,4 +21,11 @@ export const OVERWRITE_SHOW_DATASET_DIALOG_TOKEN = new InjectionToken<TOverwrite
 export type TRegionOfInterest = { ['fullId']: string }
 
 export const REGION_OF_INTEREST = new InjectionToken<Observable<TRegionOfInterest>>('RegionOfInterest')
-export const CANCELLABLE_DIALOG = new InjectionToken('CANCELLABLE_DIALOG')
\ No newline at end of file
+export const CANCELLABLE_DIALOG = new InjectionToken('CANCELLABLE_DIALOG')
+
+export type TTemplateImage = {
+  name: string
+  '@id': string
+  ngId: string
+  visible: boolean
+}
diff --git a/src/util/patchPureConstants.ts b/src/util/patchPureConstants.ts
index 55ff455615c145c59ac2906fba55625fabdf6d1a..a8fc56c9236692ad2d46c459476b69836c147898 100644
--- a/src/util/patchPureConstants.ts
+++ b/src/util/patchPureConstants.ts
@@ -6,7 +6,7 @@
  */
 
 import { IHasId } from "./interfaces";
-import { TRegion } from "./siibraApiConstants/types";
+import { TRegionSummary } from "./siibraApiConstants/types";
 
 type TAppend = {
   parent: IHasId | { name: string }
@@ -22,7 +22,7 @@ type TPatchRegion = {
   '@id': string
   targetSpace: IHasId[] | '*'
   targetParcellation: IHasId[] | '*'
-  payload: Partial<TRegion>
+  payload: Partial<TRegionSummary>
 } & (TAppend | TPatch)
 
 const encoder = new TextEncoder()
@@ -46,25 +46,21 @@ async function getInterpolatedPatchObj(targetName: string, labelIndex: number){
       '@id': 'minds/core/referencespace/v1.0.0/a1655b99-82f1-420f-a3c2-fe80fd4c8588'
     }],
     "payload": {
-      "volumeSrc": {
-        'minds/core/referencespace/v1.0.0/a1655b99-82f1-420f-a3c2-fe80fd4c8588': {
-          "collect": [{
-            "@type": "fzj/tmp/volume_type/v0.0.1" as const,
-            "@id": "fzj/tmp/volume_type/v0.0.1/interpolated",
-            "name": "Julich Brain v2.5 interpolated map",
-            "volume_type": "neuroglancer/precomputed" as const,
-            "url": "https://neuroglancer.humanbrainproject.org/precomputed/BigBrainRelease.2015/2019_05_22_interpolated_areas",
-            "detail": {
-              "neuroglancer/precomputed": {
-                "labelIndex": labelIndex,
-                "transform": [[1,0,0,-70677184],[0,1,0,-51990000],[0,0,1,-58788284],[0,0,0,1]]
-              }
-            },
-            "space_id": "minds/core/referencespace/v1.0.0/a1655b99-82f1-420f-a3c2-fe80fd4c8588",
-            map_type: 'labelled'
-          }]
-        }
-      }
+      _dataset_specs: [{
+        "@type": "fzj/tmp/volume_type/v0.0.1" as const,
+        "@id": "fzj/tmp/volume_type/v0.0.1/interpolated",
+        "name": "Julich Brain v2.5 interpolated map",
+        "volume_type": "neuroglancer/precomputed" as const,
+        "url": "https://neuroglancer.humanbrainproject.org/precomputed/BigBrainRelease.2015/2019_05_22_interpolated_areas",
+        "detail": {
+          "neuroglancer/precomputed": {
+            "labelIndex": labelIndex,
+            "transform": [[1,0,0,-70677184],[0,1,0,-51990000],[0,0,1,-58788284],[0,0,0,1]]
+          }
+        },
+        "space_id": "minds/core/referencespace/v1.0.0/a1655b99-82f1-420f-a3c2-fe80fd4c8588",
+        map_type: 'labelled'
+      }],
     }
   }
   const hex = await getShaDigest(JSON.stringify(returnObj))
@@ -78,9 +74,9 @@ async function getIndividualMap(parentName: string, regionName: string, url: str
   const volumeId = await getShaDigest(url)
   const returnObj: TPatchRegion = {
     '@id': '',
-    "@type": 'julich/siibra/append-region/v0.0.1',
-    "parent": {
-      "name": parentName
+    "@type": 'julich/siibra/patch-region/v0.0.1',
+    "target": {
+      "name": regionName
     },
     "targetParcellation": [{
       "@id": 'minds/core/parcellationatlas/v1.0.0/94c1125b-b87e-45e4-901c-00daee7f2579-290'
@@ -89,26 +85,21 @@ async function getIndividualMap(parentName: string, regionName: string, url: str
       '@id': 'minds/core/referencespace/v1.0.0/a1655b99-82f1-420f-a3c2-fe80fd4c8588'
     }],
     "payload": {
-      "name": regionName,
-      "volumeSrc": {
-        'minds/core/referencespace/v1.0.0/a1655b99-82f1-420f-a3c2-fe80fd4c8588': {
-          "collect": [{
-            "@type": "fzj/tmp/volume_type/v0.0.1" as const,
-            "@id": `fzj/tmp/volume_type/v0.0.1/${volumeId}`,
-            "name": "Julich Brain v2.5 detailed map",
-            "volume_type": "neuroglancer/precomputed" as const,
-            "url": url,
-            "detail": {
-              "neuroglancer/precomputed": {
-                "labelIndex": labelIndex,
-                "transform": transform
-              }
-            },
-            space_id: 'minds/core/referencespace/v1.0.0/a1655b99-82f1-420f-a3c2-fe80fd4c8588',
-            map_type: 'labelled'
-          }]
-        }
-      }
+      '_dataset_specs': [{
+        "@type": "fzj/tmp/volume_type/v0.0.1" as const,
+        "@id": `fzj/tmp/volume_type/v0.0.1/${volumeId}`,
+        "name": "Julich Brain v2.5 detailed map",
+        "volume_type": "neuroglancer/precomputed" as const,
+        "url": url,
+        "detail": {
+          "neuroglancer/precomputed": {
+            "labelIndex": labelIndex,
+            "transform": transform
+          }
+        },
+        space_id: 'minds/core/referencespace/v1.0.0/a1655b99-82f1-420f-a3c2-fe80fd4c8588',
+        map_type: 'labelled'
+      }],
     }
   }
   const hex = await getShaDigest(JSON.stringify(returnObj))
diff --git a/src/util/pureConstant.service.spec.ts b/src/util/pureConstant.service.spec.ts
index 2ca6fb127878caace8d1fdf0d5049a65bd2cc2af..28c60d696e3648daafefe1e70a48fd85aa0f853f 100644
--- a/src/util/pureConstant.service.spec.ts
+++ b/src/util/pureConstant.service.spec.ts
@@ -1,11 +1,11 @@
 import { HttpClientTestingModule, HttpTestingController } from "@angular/common/http/testing"
 import { TestBed } from "@angular/core/testing"
+import { MatSnackBarModule } from "@angular/material/snack-bar"
 import { MockStore, provideMockStore } from "@ngrx/store/testing"
-import { hot } from "jasmine-marbles"
 import { BS_ENDPOINT } from "src/atlasComponents/regionalFeatures/bsFeatures"
 import { AtlasWorkerService } from "src/atlasViewer/atlasViewer.workerService.service"
 import { viewerStateFetchedAtlasesSelector, viewerStateFetchedTemplatesSelector } from "src/services/state/viewerState/selectors"
-import { PureContantService } from "./pureConstant.service"
+import { PureContantService, SIIBRA_API_VERSION_HEADER_KEY } from "./pureConstant.service"
 import { TAtlas } from "./siibraApiConstants/types"
 
 const MOCK_BS_ENDPOINT = `http://localhost:1234`
@@ -17,6 +17,7 @@ describe('> pureConstant.service.ts', () => {
       TestBed.configureTestingModule({
         imports:[
           HttpClientTestingModule,
+          MatSnackBarModule,
         ],
         providers: [
           provideMockStore(),
@@ -65,7 +66,11 @@ describe('> pureConstant.service.ts', () => {
       it('> can be init, and configuration emits allFetchingReady$', () => {
         const service = TestBed.inject(PureContantService)
         const exp = httpController.expectOne(`${MOCK_BS_ENDPOINT}/atlases`)
-        exp.flush([mockAtlas])
+        exp.flush([mockAtlas], {
+          headers: {
+            [SIIBRA_API_VERSION_HEADER_KEY]: '0.1.5'
+          }
+        })
         service.allFetchingReady$.subscribe()
 
         const expT1 = httpController.expectOne(`${MOCK_BS_ENDPOINT}/atlases/${encodeURIComponent(mockAtlas.id)}/spaces`)
diff --git a/src/util/pureConstant.service.ts b/src/util/pureConstant.service.ts
index 09b2e1898137bcedd28fd9a0f3181d17b6d32778..609ebb9c43dcc51142a12a55783077a1cf65c392 100644
--- a/src/util/pureConstant.service.ts
+++ b/src/util/pureConstant.service.ts
@@ -9,11 +9,15 @@ import { LoggingService } from "src/logging";
 import { viewerStateFetchedAtlasesSelector, viewerStateSelectedTemplateSelector } from "src/services/state/viewerState/selectors";
 import { BS_ENDPOINT, BACKENDURL } from "src/util/constants";
 import { flattenReducer } from 'common/util'
-import { IVolumeTypeDetail, TAtlas, TId, TParc, TRegion, TRegionDetail, TSpaceFull, TSpaceSummary, TVolumeSrc } from "./siibraApiConstants/types";
+import { IVolumeTypeDetail, TAtlas, TId, TParc, TRegionDetail, TRegionSummary, TSpaceFull, TSpaceSummary, TVolumeSrc } from "./siibraApiConstants/types";
 import { MultiDimMap, recursiveMutate, mutateDeepMerge } from "./fn";
 import { patchRegions } from './patchPureConstants'
 import { environment } from "src/environments/environment";
+import { MatSnackBar } from "@angular/material/snack-bar";
+import { TTemplateImage } from "./interfaces";
 
+export const SIIBRA_API_VERSION_HEADER_KEY='x-siibra-api-version'
+export const SIIBRA_API_VERSION = '0.1.5'
 
 const validVolumeType = new Set([
   'neuroglancer/precomputed',
@@ -52,7 +56,7 @@ type TIAVAtlas = {
   } & THasId)[]
 } & THasId
 
-const spaceMiscInfoMap = new Map([
+export const spaceMiscInfoMap = new Map([
   ['minds/core/referencespace/v1.0.0/a1655b99-82f1-420f-a3c2-fe80fd4c8588', {
     name: 'bigbrain',
     scale: 1,
@@ -213,7 +217,7 @@ Raise/track issues at github repo: <a target = "_blank" href = "${this.repoUrl}"
   )
 
   private getRegions(atlasId: string, parcId: string, spaceId: string){
-    return this.http.get<TRegion[]>(
+    return this.http.get<TRegionSummary[]>(
       `${this.bsEndpoint}/atlases/${encodeURIComponent(atlasId)}/parcellations/${encodeURIComponent(parcId)}/regions`,
       {
         params: {
@@ -249,7 +253,7 @@ Raise/track issues at github repo: <a target = "_blank" href = "${this.repoUrl}"
                   if (p.parent['name'] === region.name) {
                     if (!region.children) region.children = []
                     region.children.push(
-                      p.payload as TRegion
+                      p.payload as TRegionSummary
                     )
                   }
                 }
@@ -375,6 +379,7 @@ Raise/track issues at github repo: <a target = "_blank" href = "${this.repoUrl}"
     private store: Store<any>,
     private http: HttpClient,
     private log: LoggingService,
+    private snackbar: MatSnackBar,
     @Inject(BS_ENDPOINT) private bsEndpoint: string,
   ){
     this.darktheme$ = this.store.pipe(
@@ -420,13 +425,24 @@ Raise/track issues at github repo: <a target = "_blank" href = "${this.repoUrl}"
   private getAtlases$ = this.http.get<TAtlas[]>(
     `${this.bsEndpoint}/atlases`,
     {
-      responseType: 'json'
+      observe: 'response'
     }
   ).pipe(
-    map(arr => {
+    tap(resp => {
+      const respVersion = resp.headers.get(SIIBRA_API_VERSION_HEADER_KEY)
+      if (respVersion !== SIIBRA_API_VERSION) {
+        this.snackbar.open(`Expecting ${SIIBRA_API_VERSION}, got ${respVersion}. Some functionalities may not work as expected.`, 'Dismiss', {
+          duration: 5000
+        })
+      }
+      console.log(`siibra-api::version::${respVersion}, expecting::${SIIBRA_API_VERSION}`)
+    }),
+    map(resp => {
+      const arr = resp.body
       const { EXPERIMENTAL_FEATURE_FLAG } = environment
       if (EXPERIMENTAL_FEATURE_FLAG) return arr
-      return arr.filter(atlas => !/pre.?release/i.test(atlas.name))
+      return arr
+      // return arr.filter(atlas => !/pre.?release/i.test(atlas.name))
     }),
     shareReplay(1),
   )
@@ -532,20 +548,20 @@ Raise/track issues at github repo: <a target = "_blank" href = "${this.repoUrl}"
                              * this should work for both fully mapped and interpolated
                              * in the case of interpolated, it sucks that the ngLayerObj will be set multiple times
                              */
-                            if (
-                              tmpl.id in (region.volumeSrc || {})
-                              && 'collect' in region.volumeSrc[tmpl.id]
-                            ) {
-                              const dedicatedMap = region.volumeSrc[tmpl.id]['collect'].filter(v => v.volume_type === 'neuroglancer/precomputed')
-                              if (dedicatedMap.length === 1) {
-                                const ngId = getNgId(atlas['@id'], tmpl.id, parc.id, dedicatedMap[0]['@id'])
-                                region['ngId'] = ngId
-                                region['labelIndex'] = dedicatedMap[0].detail['neuroglancer/precomputed'].labelIndex
-                                ngLayerObj[tmpl.id][ngId] = {
-                                  source: `precomputed://${dedicatedMap[0].url}`,
-                                  type: "segmentation",
-                                  transform: dedicatedMap[0].detail['neuroglancer/precomputed'].transform
-                                }
+
+                            const dedicatedMap = region._dataset_specs.filter(
+                              spec => spec["@type"] === 'fzj/tmp/volume_type/v0.0.1'
+                              && spec.space_id === tmpl.id
+                              && spec['volume_type'] === 'neuroglancer/precomputed'
+                            ) as TVolumeSrc<'neuroglancer/precomputed'>[]
+                            if (dedicatedMap.length === 1) {
+                              const ngId = getNgId(atlas['@id'], tmpl.id, parc.id, dedicatedMap[0]['@id'])
+                              region['ngId'] = ngId
+                              region['labelIndex'] = dedicatedMap[0].detail['neuroglancer/precomputed'].labelIndex
+                              ngLayerObj[tmpl.id][ngId] = {
+                                source: `precomputed://${dedicatedMap[0].url}`,
+                                type: "segmentation",
+                                transform: dedicatedMap[0].detail['neuroglancer/precomputed'].transform
                               }
                             }
   
@@ -579,10 +595,11 @@ Raise/track issues at github repo: <a target = "_blank" href = "${this.repoUrl}"
                                 && hemisphereKey === 'whole brain'
                               ) {
                                 region.children = []
-                                return
                               }
-                              const hemispheredNgId = getNgId(atlas['@id'], tmpl.id, parc.id, hemisphereKey)
-                              region['ngId'] = hemispheredNgId
+                              if (!region['ngId']) {
+                                const hemispheredNgId = getNgId(atlas['@id'], tmpl.id, parc.id, hemisphereKey)
+                                region['ngId'] = hemispheredNgId
+                              }
                             }
                           }  
                         )
@@ -729,16 +746,30 @@ Raise/track issues at github repo: <a target = "_blank" href = "${this.repoUrl}"
               const nehubaConfig = getNehubaConfig(tmpl)
               const initialLayers = nehubaConfig.dataset.initialNgState.layers
               
-              const tmplNgId = tmpl.name
               const tmplAuxMesh = `${tmpl.name} auxmesh`
 
-              const precomputed = tmpl._dataset_specs.find(src => src["@type"] === 'fzj/tmp/volume_type/v0.0.1' && src.volume_type === 'neuroglancer/precomputed') as TVolumeSrc<'neuroglancer/precomputed'>
-              if (precomputed) {
-                initialLayers[tmplNgId] = {
+              const precomputedArr = tmpl._dataset_specs.filter(src => src['@type'] === 'fzj/tmp/volume_type/v0.0.1' && src.volume_type === 'neuroglancer/precomputed') as TVolumeSrc<'neuroglancer/precomputed'>[]
+              let visible = true
+              let tmplNgId: string
+              let templateImages: TTemplateImage[] = []
+              for (const precomputedItem of precomputedArr) {
+                const ngIdKey = MultiDimMap.GetKey(precomputedItem["@id"])
+                initialLayers[ngIdKey] = {
                   type: "image",
-                  source: `precomputed://${precomputed.url}`,
-                  transform: precomputed.detail['neuroglancer/precomputed'].transform
+                  source: `precomputed://${precomputedItem.url}`,
+                  transform: precomputedItem.detail['neuroglancer/precomputed'].transform,
+                  visible
+                }
+                templateImages.push({
+                  "@id": precomputedItem['@id'],
+                  name: precomputedItem.name,
+                  ngId: ngIdKey,
+                  visible
+                })
+                if (visible) {
+                  tmplNgId = ngIdKey
                 }
+                visible = false
               }
 
               // TODO
@@ -776,6 +807,7 @@ Raise/track issues at github repo: <a target = "_blank" href = "${this.repoUrl}"
                 useTheme: darkTheme ? 'dark' : 'light',
                 ngId: tmplNgId,
                 nehubaConfig,
+                templateImages,
                 auxMeshes,
                 /**
                  * only populate the parcelltions made available
diff --git a/src/util/siibraApiConstants/fn.ts b/src/util/siibraApiConstants/fn.ts
index d1cc7ff554d14490b1ae1d9915d10ff1dbcaba4b..0316b8c94f93b5c9bd0d65f8ed0aa957fe918847 100644
--- a/src/util/siibraApiConstants/fn.ts
+++ b/src/util/siibraApiConstants/fn.ts
@@ -1,7 +1,8 @@
 import { TRegionDetail } from "./types";
 
 export function getPosFromRegion(region: TRegionDetail){
-  if (!region?.props) return null
-  if (!region.props.components?.[0]) return null
-  return region.props.components[0].centroid.map(v => v*1e6) as [number, number, number]
+  if (!!region?.props?.components?.[0]?.centroid) {
+    return region.props.components[0].centroid.map(v => v*1e6) as [number, number, number]  
+  }
+  return null
 }
\ No newline at end of file
diff --git a/src/util/siibraApiConstants/types.ts b/src/util/siibraApiConstants/types.ts
index 62fc6057d749a4123da76bcce3bf2d6b2fd738be..40feae057c4f86091709af44a3346ce8fdb3b2bb 100644
--- a/src/util/siibraApiConstants/types.ts
+++ b/src/util/siibraApiConstants/types.ts
@@ -96,7 +96,14 @@ export type TParcSummary = {
   name: string
 }
 
-export type TDatainfos = {
+export type TDatainfoSummary = {
+  '@type': 'minds/core/dataset/v1.0.0'
+  kgSchema: string
+  kgId: string
+}
+
+export type TDatainfosDetail = {
+  '@type': 'minds/core/dataset/v1.0.0'
   name: string
   description: string
   urls: {
@@ -148,22 +155,37 @@ export type TParc = {
   _dataset_specs: TDatasetSpec[]
 }
 
+export type TRegionSummary = {
+  name: string
+  labelIndex: number
+  rgb: [number, number, number]
+  id: number
+  availableIn: {
+    id: string
+    name: string
+  }[]
+  _dataset_specs: (TVolumeSrc<keyof IVolumeTypeDetail> | TDatainfoSummary)[]
+  children: TRegionSummary[]
+}
+
 export type TRegionDetail = {
   name: string
-  children: TRegionDetail[]
-  rgb: number[]
-  id: string
   labelIndex: number
-  volumeSrc: {
-    [key: string]: {
-      [key: string]: TVolumeSrc<keyof IVolumeTypeDetail>[]
-    }
+  rgb: [number, number, number]
+  id: {
+    kg: TKgIdentifier
   }
   availableIn: {
     id: string
     name: string
   }[]
+  _dataset_specs: (TVolumeSrc<keyof IVolumeTypeDetail> | TDatainfosDetail)[]
+
+  children: TRegionDetail[]
   hasRegionalMap: boolean
+  links: {
+    [key: string]: string
+  }
   props: {
     components: {
       centroid: [number, number, number]
@@ -171,34 +193,6 @@ export type TRegionDetail = {
     }[]
     space: any
   }
-  links: {
-    [key: string]: string
-  }
-  originDatainfos: TDatainfos[]
+  
 }
 
-export type TRegion = {
-  name: string
-  children: TRegion[]
-  volumeSrc: {
-    [key: string]: {
-      [key: string]: TVolumeSrc<keyof IVolumeTypeDetail>[]
-    }
-  }
-
-  labelIndex?: number
-  rgb?: number[]
-  id?: {
-    kg: TKgIdentifier
-  }
-
-  /**
-   * missing 
-   */
-
-  originDatasets?: ({
-    filename: string
-  } & TKgIdentifier) []
-
-  position?: number[]
-}
diff --git a/src/viewerModule/viewerStateBreadCrumb/breadcrumb/breadcrumb.component.ts b/src/viewerModule/viewerStateBreadCrumb/breadcrumb/breadcrumb.component.ts
index a57a22a767a5acda4826f2c46577a6d25e29b78f..8bf705e68d933cdc60faa91903cb9506025c2895 100644
--- a/src/viewerModule/viewerStateBreadCrumb/breadcrumb/breadcrumb.component.ts
+++ b/src/viewerModule/viewerStateBreadCrumb/breadcrumb/breadcrumb.component.ts
@@ -7,7 +7,7 @@ import { distinctUntilChanged, map } from "rxjs/operators";
 import { viewerStateHelperSelectParcellationWithId, viewerStateRemoveAdditionalLayer, viewerStateSetSelectedRegions } from "src/services/state/viewerState.store.helper";
 import { ngViewerActionClearView, ngViewerSelectorClearViewEntries } from "src/services/state/ngViewerState.store.helper";
 import { OVERWRITE_SHOW_DATASET_DIALOG_TOKEN } from "src/util/interfaces";
-import { TDatainfos, TParc, TSimpleInfo } from "src/util/siibraApiConstants/types";
+import { TDatainfosDetail } from "src/util/siibraApiConstants/types";
 
 @Component({
   selector: 'viewer-state-breadcrumb',
@@ -120,10 +120,11 @@ export class ViewerStateBreadCrumb {
 })
 
 export class OriginalDatainfoPipe implements PipeTransform{
-  public transform(arr: TDatainfos[]): TDatainfos[]{
+  public transform(arr: TDatainfosDetail[]): TDatainfosDetail[]{
     if (arr.length > 0) {
       return arr.map(d => {
         return {
+          '@type': 'minds/core/dataset/v1.0.0',
           name: d.name,
           description: d.name,
           urls: [],