diff --git a/README.md b/README.md
index e5b7a7b2c0b43ab46b68a35faa8e59b9989974b2..a6c762757b71bd98e94d102e2a3a255ea9339340 100644
--- a/README.md
+++ b/README.md
@@ -7,103 +7,204 @@ Interactive Atlas Viewer is an frontend module wrapping around [nehuba](https://
 A live version of the Interactive Atlas Viewer is available at [https://interactive-viewer.apps.hbp.eu](https://interactive-viewer.apps.hbp.eu). This section is useful for developers who would like to develop this project.
 
 ### General information
-Interactive atlas viewer is built with [Angular (v6.0)](https://angular.io/), [Bootstrap (v4)](http://getbootstrap.com/), and [fontawesome icons](https://fontawesome.com/). Some other notable packages used are [ngrx/store](https://github.com/ngrx/platform) for state management. 
+Interactive atlas viewer is built with [Angular (v9.0)](https://angular.io/), [Bootstrap (v4)](http://getbootstrap.com/), and [fontawesome icons](https://fontawesome.com/). Some other notable packages used are [ngrx/store](https://github.com/ngrx/platform) for state management. 
 
 Releases newer than [v0.2.9](https://github.com/HumanBrainProject/interactive-viewer/tree/v0.2.9) also uses a nodejs backend, which uses [passportjs](http://www.passportjs.org/) for user authentication, [express](https://expressjs.com/) as a http framework.
 
-### Prerequisites
+### Develop viewer
+
+#### Prerequisites
 
 - node >= 12
 
-### Develop Interactive Viewer
+#### Buildtime environments
+
+It is recommended to manage your environments with `.env` file.
+
+As interactive atlas viewer uses [webpack define plugin](https://webpack.js.org/plugins/define-plugin/), where necessary, the environmental variables are `JSON.stringify`'ed and directly replaced in the code.
+
+| name | description | default | example |
+| --- | --- | --- | --- |
+| `VERSION` | printed in console on viewer startup | `GIT_HASH` \|\| unspecificed hash | v2.2.2 |
+| `PRODUCTION` | if the build is for production, toggles optimisations such as minification | `undefined` | true |
+| `BACKEND_URL` | backend that the viewer calls to fetch available template spaces, parcellations, plugins, datasets | `null` | https://interactive-viewer.apps.hbp.eu/ |
+| `DATASET_PREVIEW_URL` | dataset preview url used by component <https://github.com/fzj-inm1-bda/kg-dataset-previewer>. Useful for diagnosing issues with dataset previews.| https://hbp-kg-dataset-previewer.apps.hbp.eu/datasetPreview | http://localhost:1234/datasetPreview |
+| `MATOMO_URL` | base url for matomo analytics | `null` | https://example.com/matomo/ |
+| `MATOMO_ID` | application id for matomo analytics | `null` | 6 |
+| `USE_LOGO` | possible values are `hbp`, `ebrains`, `fzj` | `hbp` | `ebrains` |
+| `STRICT_LOCAL` | hides **Explore** and **Download** buttons. Useful for offline demo's | `false` | `true` |
+| `KIOSK_MODE` | after 5 minutes of inactivity, shows overlay inviting users to interact | `false` | `true` |
+| `BUILD_TEXT` | overlay text at bottom right of the viewer. set to `''` to hide. | |
+
+#### Deploy environments
+
+It is recommended to manage your environments with `.env` file.
+
+##### Application
+
+| name | description | default | example |
+| --- | --- | --- | --- |
+| `PORT` | port to listen on | 3000 |
+| `HOST_PATHNAME` | pathname to listen on, restrictions: leading slash, no trailing slash | `''` | `/viewer` |
+| `SESSIONSECRET` | session secret for cookie session |
+| `NODE_ENV` | determines where the built viewer will be served from | | `production` |
+| `PRECOMPUTED_SERVER` | redirect data uri to another server. Useful for offline demos | | `http://localhost:8080/precomputed/` |
+| `LOCAL_CDN` | rewrite cdns to local server. useful for offlnie demo | | `http://localhost:7080/` |
+| `PLUGIN_URLS` | semi colon separated urls to be returned when user queries plugins | `''`
+| `STAGING_PLUGIN_URLS` | semi colon separated urls to be returned when user queries plugins | `''`
+
+
+##### ebrains user authentication
+
+| name | description | default | example |
+| --- | --- | --- | --- |
+| `HOSTNAME` | 
+| `HBP_CLIENTID` | `{HOSTNAME}{HOST_PATHNAME}/hbp-oidc/cb` |
+| `HBP_CLIENTSECRET` |
+| `HBP_CLIENTID_V2` | `{HOSTNAME}{HOST_PATHNAME}/hbp-oidc-v2/cb`
+| `HBP_CLIENTSECRET_V2` | 
+
+##### Querying ebrains knowledge graph
+
+| name | description | default | example |
+| --- | --- | --- | --- |
+| `REFRESH_TOKEN` |
+| `ACCESS_TOKEN` | **nb** as access tokens are usually short lived, this should only be set for development purposes 
+| `CACHE_DATASET_FILENAME` | | `deploy/dataset/cachedKgDataset.json` |
+| `KG_ROOT` | | `https://kg.humanbrainproject.eu/query` |
+| `KG_SEARCH_VOCAB` | | `https://schema.hbp.eu/myQuery/` |
+| `KG_DATASET_SEARCH_QUERY_NAME` | | `interactiveViewerKgQuery-v0_3` |
+| `KG_DATASET_SEARCH_PATH` | | `/minds/core/dataset/v1.0.0` |
+| `KG_SEARCH_SIZE` | | `1000` |
+| `KG_SPATIAL_DATASET_SEARCH_QUERY_NAME` | | `iav-spatial-query-v2` |
+| `KG_SPATIAL_DATASET_SEARCH_PATH` | | `/neuroglancer/seeg/coordinate/v1.0.0` | 
+
+##### Logging
+
+| name | description | default | example |
+| --- | --- | --- | --- |
+| `FLUENT_PROTOCOL` | protocol for fluent logging | `http` |
+| `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
+
+| name | description | default | example |
+| --- | --- | --- | --- |
+| `DISABLE_CSP` | disable csp | | `true` |
+| `CSP_REPORT_URI` | report uri for csp violations | `/report-violation` |
+| `NODE_ENV` | set to `production` to disable [`reportOnly`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only) | `null` |
+| `SCRIPT_SRC` | `JSON.stringify`'ed array of allowed scriptSrc | `[]` |
+| `DATA_SRC` | `JSON.stringify`'ed array of allowed dataSrc | `[]` |
+| `WHITE_LIST_SRC` | `JSON.stringify`'ed array of allowed src | `[]` |
+| `PROXY_HOSTNAME_WHITELIST` |
+
+##### Rate limiting
+
+| name | description | default | example |
+| --- | --- | --- | --- |
+| `REDIS_PROTO` | fall back to `REDIS_RATE_LIMITING_DB_EPHEMERAL_PORT_6379_TCP_PROTO` |
+| `REDIS_ADDR` | fall back to `REDIS_RATE_LIMITING_DB_EPHEMERAL_PORT_6379_TCP_ADDR` |
+| `REDIS_PORT` | fall back to `REDIS_RATE_LIMITING_DB_EPHEMERAL_PORT_6379_TCP_PORT` |
+| `REDIS_USERNAME` |
+| `REDIS_PASSWORD` |
+| `DISABLE_LIMITER` | disable rate limiting (maybe required for automated tests) |
+
+##### SaneUrl
+
+| name | description | default | example |
+| --- | --- | --- | --- |
+| `OBJ_STORAGE_AUTH_URL` |
+| `OBJ_STORAGE_IDP_NAME` |
+| `OBJ_STORAGE_IDP_PROTO` |
+| `OBJ_STORAGE_IDP_URL` |
+| `OBJ_STORAGE_USERNAME` |
+| `OBJ_STORAGE_PASSWORD` |
+| `OBJ_STORAGE_PROJECT_ID` |
+| `OBJ_STORAGE_ROOT_URL` |
+
+##### Test deploy denvironments
+
+| name | description | default | example |
+| --- | --- | --- | --- |
+| `SERVICE_ACCOUNT_CRED` | 
+| `SERVICE_ACCOUNT_CRED_PATH` | 
+| `WAXHOLM_RAT_GOOGLE_SHEET_ID` |
+| `SKIP_RETRY_TEST` | retry tests contains some timeouts, which may slow down tests | 
+
+#### Start dev server
 
 To run a dev server, run:
 
-```
+```bash
 $ git clone https://github.com/HumanBrainProject/interactive-viewer
 $ cd interactive-viewer
 $ npm i
-$ npm run dev
+$ npm run dev-server
 ```
 
-### Develop Plugins
-
-For releases newer than [v0.2.9](https://github.com/HumanBrainProject/interactive-viewer/tree/v0.2.9), Interactive Atlas Viewer attempts to fetch `GET {BACKEND_URL}/plugins` to retrieve a list of URLs. The interactive atlas viewer will then perform a `GET` request for each of the listed URLs, parsing them as [manifests](src/plugin_examples/README.md#Manifest%20JSON).
+Start backend (in a separate terminal):
 
-The backend reads the environment variable `PLUGIN_URLS` and separate the string with `;` as a delimiter. In order to return a response akin to the following:
-
-```JSON
-["http://localhost:3001/manifest.json","http://localhost:9001/manifest.json"]
+```bash
+$ cd deploy
+$ node server.js
 ```
 
-Plugin developers may choose to do any of the following:
-
-_shell_
-
-set env var every time
+#### Build
 
 ```bash
-$ PLUGIN_URLS=http://localhost:3001/manifest.json;http://localhost:9001/manifest.json npm run dev
+$ npm run build-aot
 ```
 
-_dotenv_
+### Develop plugins
 
-set a `.env` file in `./deploy/` once
+Below demonstrates an example workflow for developing plugins:
 
 ```bash
-$ echo `PLUGIN_URLS=http://localhost:3001/manifest.json;http://localhost:9001/manifest.json` > ./deploy/.env
-```
-
-then, simple start the dev process with
 
-```bash
-$ npm run dev
+$ # build aot version of the atlas viewer
+$ npm run build-aot
+$ cd deploy
+$ # run server with PLUGIN_URLS
+$ PLUGIN_URLS=http://localhost:3333/manifest.json;http://localhost:3334/manifest.json node server.js
 ```
 
-Plugin developers can start their own webserver, use [interactive-viewer-plugin-template](https://github.com/HumanBrainProject/interactive-viewer-plugin-template), or (coming soon) provide link to a github repository.
-
-
-[plugin readme](src/plugin_examples/README.md)
-
-[plugin api](src/plugin_examples/plugin_api.md)
-
-[plugin migration guide](src/plugin_examples/migrationGuide.md)
+Interactive Atlas Viewer attempts to fetch list of manifests:
 
+```
+GET {BACKEND_URL}/plugins
+```
 
-## Compilation
+The response from this endpoint will be:
 
-`package.json` provide with two ways of building the interactive atlas viewer, `JIT` or `AOT` compilation. In general, `AOT` compilation produces a smaller package and has better performance. 
+```json
+[
+  "http://localhost:3333/manifest.json",
+  "http://localhost:3334/manifest.json"
+]
+```
 
-### AOT compilation
+When user launches the viewer, the atlas viewer will attempt to fetch the metadata of the plugins:
 
 ```
-npm run build-aot
+GET http://localhost:3333/manifest.json
+GET http://localhost:3334/manifest.json
 ```
 
-### JIT Compilation
-```
-npm run build
-
-/* OR */
+The response from these endpoints are expected to adhere to [manifests](src/plugin_examples/README.md#Manifest%20JSON).
 
-npm run build-min
-```
+When the user launches the plugin, the viewer will fetch `templateUrl` and `scriptUrl`, if necessary.
 
-### Docker
+Plugin developers can start their own webserver, use [interactive-viewer-plugin-template](https://github.com/HumanBrainProject/interactive-viewer-plugin-template), or (coming soon) provide link to a github repository.
 
-The repository also provides a `Dockerfile`. Here are the environment variables used:
 
-_build time_
-- __BACKEND_URL__ : same as `HOSTNAME` during run time. Needed as root URL when fetching templates / datasets etc. If left empty, will fetch without hostname.
+[plugin readme](src/plugin_examples/README.md)
 
-_run time_
+[plugin api](src/plugin_examples/plugin_api.md)
 
-- __SESSION_SECRET__ : needed for session
-- __HOSTNAME__ : needed for OIDC redirect
-- __HBP_CLIENTID__ : neded for OIDC authentication
-- __HBP_CLIENTSECRET__ : needed for OIDC authentication
-- __PLUGIN_URLS__ : optional. Allows plugins to be populated
-- __REFRESH_TOKEN__ : needed for access of public data
+[plugin migration guide](src/plugin_examples/migrationGuide.md)
 
 ## Contributing
 
@@ -115,4 +216,4 @@ Commit history prior to v0.2.0 is available in the [legacy-v0.2.0](https://githu
 
 ## License
 
-TO BE DECIDED
\ No newline at end of file
+Apache-2.0
\ No newline at end of file
diff --git a/deploy/datasets/supplements/previewFile.js b/deploy/datasets/supplements/previewFile.js
index 976d646879e7ab6ecb4ff3acba8d61eb4dedec7d..8a48ef0170861cf3e378f6fb7c04118ef5f297a2 100644
--- a/deploy/datasets/supplements/previewFile.js
+++ b/deploy/datasets/supplements/previewFile.js
@@ -1,3 +1,7 @@
+/**
+ * TODO deprecate?
+ */
+
 const fs = require('fs')
 const path = require('path')
 const { reconfigureFlag, reconfigureUrl } = require('../../util/reconfigPrecomputedServer')
diff --git a/docs/releases/v2.2.2.md b/docs/releases/v2.2.2.md
index 575e922d91ea0efbd3b713f3a27f27d3290174cf..53f7ad660fa278288f711ab6659c575f9e68d9d3 100644
--- a/docs/releases/v2.2.2.md
+++ b/docs/releases/v2.2.2.md
@@ -1,5 +1,7 @@
 # v2.2.2
 
+7 June 2020
+
 ## Bugfixes
 
 - Fixed PMap color map reset colormap (#523)
diff --git a/docs/releases/v2.3.0.md b/docs/releases/v2.3.0.md
index 28092cb5dcabf66bca8fc8f22becb1febade1c64..da2150d30807dcd67059fe4e77df3391ffb976c2 100644
--- a/docs/releases/v2.3.0.md
+++ b/docs/releases/v2.3.0.md
@@ -1,9 +1,10 @@
 # v2.3.0
 
-## New feature
+## New features
 
 - update dataset preview functionality, allow the previewing of png
 - improved the previewing of maps
   - parse min and max, if these metadata are provided
   - allowing for color maps other than jet
+- Updated `README.md`
 - introduced zoom buttons
diff --git a/package.json b/package.json
index 29ba287e69721c55b018ed947eee23c821b2c17b..5374d29f1719113e57762405cb0996ec8e5c8c50 100644
--- a/package.json
+++ b/package.json
@@ -10,7 +10,6 @@
     "build-aot": "PRODUCTION=true GIT_HASH=`git rev-parse --short HEAD` webpack --config webpack.aot.js && node ./third_party/matomo/processMatomo.js",
     "plugin-server": "node ./src/plugin_examples/server.js",
     "dev-server": "BACKEND_URL=${BACKEND_URL:-http://localhost:3000/} webpack-dev-server --config webpack.dev.js --mode development",
-    "dev": "npm run dev-server & (cd deploy; node server.js)",
     "dev-server-aot": "BACKEND_URL=${BACKEND_URL:-http://localhost:3000/} PRODUCTION=true GIT_HASH=`git log --pretty=format:'%h' --invert-grep --grep=^.ignore -1` webpack-dev-server --config webpack.dev-aot.js",
     "dev-server-all-interfaces": "webpack-dev-server --config webpack.dev.js --mode development --hot --host 0.0.0.0",
     "test": "karma start spec/karma.conf.js",
diff --git a/src/glue.spec.ts b/src/glue.spec.ts
index f5ee1d2f46b0321c522dab6f574b6fcd6edc378f..e3b6d940d851d5dad9e0e5b6da28c044c05e9abc 100644
--- a/src/glue.spec.ts
+++ b/src/glue.spec.ts
@@ -5,11 +5,12 @@ import { provideMockStore, MockStore } from "@ngrx/store/testing"
 import { getRandomHex } from 'common/util'
 import { EnumWidgetTypes, TypeOpenedWidget, uiActionSetPreviewingDatasetFiles } from "./services/state/uiState.store.helper"
 import { hot } from "jasmine-marbles"
-import * as DATABROWSER_MODULE_EXPORTS from 'src/ui/databrowserModule'
 import { HttpClientTestingModule, HttpTestingController } from "@angular/common/http/testing"
 import { glueActionToggleDatasetPreview } from './glue'
 import { getIdObj } from 'common/util'
 import { DS_PREVIEW_URL } from 'src/util/constants'
+import { NgLayersService } from "./ui/layerbrowser/ngLayerService.service"
+import { EnumColorMapName } from "./util/colorMaps"
 
 const mockActionOnSpyReturnVal0 = { 
   id: getRandomHex(),
@@ -32,7 +33,14 @@ let actionOnWidgetSpy
 const nifti = {
   mimetype: "application/nifti",
   url: "http://abc.xyz",
-  referenceSpaces: []
+  referenceSpaces: [],
+  volumeMetadata: {
+    min: 0.1,
+    max: 0.45,
+    colormap: 'viridis'
+  },
+  name: 'helloworld',
+  filename: 'foobar'
 }
 
 const chart = {
@@ -88,7 +96,8 @@ describe('> glue.ts', () => {
           {
             provide: ACTION_TO_WIDGET_TOKEN,
             useValue: actionOnWidgetSpy
-          }
+          },
+          NgLayersService
         ]
       })
     })
@@ -247,6 +256,42 @@ describe('> glue.ts', () => {
         const req = ctrl.expectOne(`${DS_PREVIEW_URL}/${datasetId}/${encodeURIComponent(filename)}`)
         req.flush(nifti)
       }))
+
+      it('> on previewing nifti, thresholds, colormap and remove bg flag set properly', fakeAsync(() => {
+        const store = TestBed.inject(MockStore)
+        const ctrl = TestBed.inject(HttpTestingController)
+
+        const layerService = TestBed.inject(NgLayersService)
+
+        const highThresholdMapSpy = spyOn(layerService.highThresholdMap, 'set').and.callThrough()
+        const lowThresholdMapSpy = spyOn(layerService.lowThresholdMap, 'set').and.callThrough()
+        const colorMapMapSpy = spyOn(layerService.colorMapMap, 'set').and.callThrough()
+        const bgFlagSpy = spyOn(layerService.removeBgMap, 'set').and.callThrough()
+
+        const glue = TestBed.inject(DatasetPreviewGlue)
+
+        
+
+        store.setState({
+          uiState: {
+            previewingDatasetFiles: [ file1 ]
+          }
+        })
+
+        const { datasetId, filename } = file1
+        // debounce at 100ms
+        tick(200)
+
+        const req = ctrl.expectOne(`${DS_PREVIEW_URL}/${datasetId}/${encodeURIComponent(filename)}`)
+        req.flush(nifti)
+
+        const { name, volumeMetadata } = nifti
+        const { min, max } = volumeMetadata
+        expect(highThresholdMapSpy).toHaveBeenCalledWith(name, max)
+        expect(lowThresholdMapSpy).toHaveBeenCalledWith(name, min)
+        expect(colorMapMapSpy).toHaveBeenCalledWith(name, EnumColorMapName.VIRIDIS)
+        expect(bgFlagSpy).toHaveBeenCalledWith(name, true)
+      }))
     })
 
     describe('> #actionOnWidget', () => {
diff --git a/src/glue.ts b/src/glue.ts
index 7be1c6b576e6cd9fa9df0354567110892428b251..696129f96f5558c4e0c36cd3ce5523c7059bc53b 100644
--- a/src/glue.ts
+++ b/src/glue.ts
@@ -449,15 +449,6 @@ export const SAVE_USER_DATA = new InjectionToken<TypeSaveUserData>('SAVE_USER_DA
 
 type TypeSaveUserData = (key: string, value: string) => void
 
-
-@Injectable({
-  providedIn: 'root'
-})
-
-export class DatasetUserGlue {
-
-}
-
 export const gluActionFavDataset = createAction(
   '[glue] favDataset',
   props<{dataentry: Partial<IKgDataEntry>}>()
diff --git a/third_party/catchSyntaxError.js b/third_party/catchSyntaxError.js
index 4b6ef2f0d3cc71ef3677c946ff34e390e3052dc4..09218b04f306b7584e57d8342c106100ea372432 100644
--- a/third_party/catchSyntaxError.js
+++ b/third_party/catchSyntaxError.js
@@ -1,6 +1,6 @@
-(() => {
-  window.onerror = e => {
-    if (/^SyntaxError/.test(e)) {
+(function(){
+  window.onerror = function(e) {
+    if (/^SyntaxError/.test(e) || /^Syntax\serror/.test(e)) {
       console.log('Caught SyntaxError')
 
       const warning = 'Your browser cannot display the interactive viewer. Please use either Chrome >= 56 and/or Firefox >= 51'
diff --git a/typings/index.d.ts b/typings/index.d.ts
index 2fb1dc3a178d16dd8fdabb97eac85d03b031c875..72134378c71db282c8e63ab3472e6666354df982 100644
--- a/typings/index.d.ts
+++ b/typings/index.d.ts
@@ -10,8 +10,6 @@ declare module '*.css' {
 
 declare module '*.md'
 
-declare var PLUGINDEV : string
-declare var BUNDLEDPLUGINS : string[]
 declare var VERSION : string
 declare var PRODUCTION: boolean
 declare var BACKEND_URL: string
diff --git a/webpack.staticassets.js b/webpack.staticassets.js
index b5801554328eeb705ff5d5e92a2c644c5afd7a04..0f2617f68ea7db7d6695a9866ee644eb981471b1 100644
--- a/webpack.staticassets.js
+++ b/webpack.staticassets.js
@@ -55,16 +55,8 @@ module.exports = {
       filename: 'theme.css'
     }),
     new webpack.DefinePlugin({
-      // TODO deprecate
-      PLUGINDEV : process.env.PLUGINDEV
-        ? JSON.stringify(process.env.PLUGINDEV)
-        : false,
 
-      // TODO deprecate
-      BUNDLEDPLUGINS : process.env.BUNDLEDPLUGINS
-        ? JSON.stringify(process.env.BUNDLEDPLUGINS.split(','))
-        : JSON.stringify([]),
-      VERSION : process.env.VERSION 
+      VERSION: process.env.VERSION 
         ? JSON.stringify(process.env.VERSION) 
         : process.env.GIT_HASH
           ? JSON.stringify(process.env.GIT_HASH)