diff --git a/.eslintrc.js b/.eslintrc.js
index fe0ec8f038dea3da56ed33293a2a6d6c14e5cd79..54af39fd8e639934ed7c4c2658f668a4facc8536 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -20,8 +20,9 @@ module.exports = {
         "requireLast": false
       }
     }],
-    "@typescript-eslint/no-unused-vars": ["warn", {
-      "argsIgnorePattern": "^_"
+    "@typescript-eslint/no-unused-vars": ["error", {
+      "argsIgnorePattern": "^_",
+      "ignoreRestSiblings": true
     }],
     "@typescript-eslint/explicit-function-return-type": "off",
     "@typescript-eslint/no-explicit-any": "off",
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index e092ca43f6bf407a44eda7316b426e95b71ceaa2..25a2cd761b2c38a48147a54f79640b34ad0fa7ae 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -14,7 +14,7 @@ jobs:
   #   runs-on: ubuntu-latest
 
   #   steps:
-  #   - uses: actions/checkout@v2
+  #   - uses: actions/checkout@v3
   #   - uses: actions/setup-node@v1
   #     with:
   #       node-version: '16.x'
@@ -25,7 +25,7 @@ jobs:
     runs-on: ubuntu-latest
 
     steps:
-    - uses: actions/checkout@v2
+    - uses: actions/checkout@v3
     - name: Use Node.js 16.x for lint
       uses: actions/setup-node@v1
       with:
@@ -41,7 +41,7 @@ jobs:
       NODE_ENV: test
       
     steps:
-    - uses: actions/checkout@v2
+    - uses: actions/checkout@v3
     - name: Use Node.js 16.x
       uses: actions/setup-node@v1
       with:
@@ -63,7 +63,7 @@ jobs:
       NODE_ENV: test
 
     steps:
-    - uses: actions/checkout@v2
+    - uses: actions/checkout@v3
     - name: Use Node.js 16.x
       uses: actions/setup-node@v1
       with:
diff --git a/.github/workflows/docker_img.yml b/.github/workflows/docker_img.yml
index 5dd8db7891e24bf018b1f8e90164c038bf4b7b93..eb5368f03107d568f2157cbee31359bae1f03f6b 100644
--- a/.github/workflows/docker_img.yml
+++ b/.github/workflows/docker_img.yml
@@ -30,7 +30,7 @@ jobs:
         build: [ 'local', 'prod' ]
 
     steps:
-    - uses: actions/checkout@v2
+    - uses: actions/checkout@v3
     - name: 'Set matomo env var'
       # if matrix.build is local, only run if master or dev
       if: ${{ !(matrix.build == 'local' && github.ref != 'refs/heads/master' && github.ref != 'refs/heads/dev') }} 
@@ -120,7 +120,7 @@ jobs:
 
     needs: build-docker-img
     steps:
-      - uses: actions/checkout@v2
+      - uses: actions/checkout@v3
       - name: Set env var
         run: |
           echo "Using github.ref: $GITHUB_REF"
diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml
index 9203ddec11d5972bd515d88cabe518281765a226..ec46c942aebec12804baf7c73da2bd092023d55c 100644
--- a/.github/workflows/e2e.yml
+++ b/.github/workflows/e2e.yml
@@ -59,7 +59,7 @@ jobs:
       failure-state: ${{ steps.failure-state-step.outputs.failure-state }}
 
     steps:
-    - uses: actions/checkout@v2
+    - uses: actions/checkout@v3
       with:
         ref: ${{ github.event.ref }}
 
diff --git a/.github/workflows/manual_e2e.yml b/.github/workflows/manual_e2e.yml
index 9829d7053bd047b73209192c0effbb5c87715599..a55bd1e16b0aee7d9dc6c91af8aba780b2bc40ec 100644
--- a/.github/workflows/manual_e2e.yml
+++ b/.github/workflows/manual_e2e.yml
@@ -9,7 +9,7 @@ jobs:
   hide_previous_if_exists:
     runs-on: ubuntu-latest
     steps:
-    - uses: actions/checkout@v2
+    - uses: actions/checkout@v3
       with:
         ref: 'master'
     - uses: actions/github-script@v5
@@ -23,7 +23,7 @@ jobs:
     runs-on: ubuntu-latest
 
     steps:
-    - uses: actions/checkout@v2
+    - uses: actions/checkout@v3
     - name: 'Add checklist comment'
       uses: actions/github-script@v5
       with:
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 42fc00b29beb30be08b73526c02e9325fb3955ad..211fd6d9ed6b726d95894c16366837d1c743392a 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -24,7 +24,7 @@ jobs:
     if: success()
     runs-on: ubuntu-latest
     steps:
-    - uses: actions/checkout@v2
+    - uses: actions/checkout@v3
     - name: Create Release
       id: create_release
       uses: actions/create-release@v1
diff --git a/.github/workflows/repo_sync_ebrains.yml b/.github/workflows/repo_sync_ebrains.yml
index 548b768b0cd23b694a323919a7e64c71ee512d92..e29122fa0ac82239f8772e61b0d0b8581135fbd1 100644
--- a/.github/workflows/repo_sync_ebrains.yml
+++ b/.github/workflows/repo_sync_ebrains.yml
@@ -9,7 +9,7 @@ jobs:
   sync:
     runs-on: ubuntu-latest
     steps:
-    - uses: actions/checkout@v2
+    - uses: actions/checkout@v3
     - uses: wei/git-sync@v3
       with:
         source_repo: ${GITHUB_REPOSITORY}
diff --git a/common/constants.js b/common/constants.js
index 0b92fb901782e568b9c8f2db52f9f7c9a79156b3..d3fe2b2b308520de3e5e9142d58b681c9dbc2a5a 100644
--- a/common/constants.js
+++ b/common/constants.js
@@ -163,5 +163,6 @@ If you do not accept the Terms & Conditions you are not permitted to access or u
   }
 
   exports.QUICKTOUR_DESC_MD = {
+    SLICE_VIEW: `The planar views allow you to zoom \`[mouse wheel]\`, pan the view \`[drag]\`, and select oblique sections \`<shift>\` + \`[drag]\`. You can \`[click]\` any brain regions to select them.`
   }
 })(typeof exports === 'undefined' ? module.exports : exports)
diff --git a/deploy/app.js b/deploy/app.js
index 6fa78cb8a4f51179509b26e5d807c89c05a9269b..f4b3dcd07ead1a7cad8f3c987db8619c1d16e219 100644
--- a/deploy/app.js
+++ b/deploy/app.js
@@ -17,7 +17,7 @@ app.use('/quickstart', require('./quickstart'))
 
 const hash = string => crypto.createHash('sha256').update(string).digest('hex')
 
-app.use((req, _, next) => {
+app.use((req, resp, next) => {
   if (/main\.bundle\.js$/.test(req.originalUrl)){
     const xForwardedFor = req.headers['x-forwarded-for']
     const ip = req.socket.remoteAddress
@@ -28,6 +28,9 @@ app.use((req, _, next) => {
       ip: hash(ip)
     })
   }
+  if (/favicon/.test(req.originalUrl)) {
+    resp.setHeader(`Cache-Control`, `public, max-age=604800, immutable`)
+  }
   next()
 })
 
diff --git a/deploy/csp/index.js b/deploy/csp/index.js
index e976dd482d2845490dd24bebef212ea1ab0aeb17..e48f7f155e90e027e0274590f854d7281ca83bad 100644
--- a/deploy/csp/index.js
+++ b/deploy/csp/index.js
@@ -115,7 +115,7 @@ module.exports = {
           'https://unpkg.com/d3@6.2.0/', // required for preview component
           'https://unpkg.com/mathjax@3.1.2/', // math jax
           'https://unpkg.com/three-surfer@0.0.13/dist/bundle.js', // for threeSurfer (freesurfer support in browser)
-          'https://unpkg.com/ng-layer-tune@0.0.12/dist/ng-layer-tune/', // needed for ng layer control
+          'https://unpkg.com/ng-layer-tune@0.0.13/dist/ng-layer-tune/', // needed for ng layer control
           'https://unpkg.com/hbp-connectivity-component@0.6.6/', // needed for connectivity component
           (req, res) => res.locals.nonce ? `'nonce-${res.locals.nonce}'` : null,
           ...SCRIPT_SRC,
diff --git a/docs/releases/v2.11.2.md b/docs/releases/v2.11.2.md
new file mode 100644
index 0000000000000000000000000000000000000000..e541eb07514392266014c0442ea8acbd7a6f41a6
--- /dev/null
+++ b/docs/releases/v2.11.2.md
@@ -0,0 +1,19 @@
+# v2.11.2
+
+## Features
+
+- Allow external layer control to persist state (#1338)
+
+## Bugfixes
+
+- Fixed point assignment for maps that do not have statistical maps. Also fixed error messages.
+- Fixed neuron display
+- Fixed typos in plugin API messages
+- Fixed fsaverage toggle delineation only affecting hemisphere
+
+## Behind the scenes
+
+- Using hashed region name to encode selected region, rather than the archaic ngId & label index
+- Pass messages to plugin API when not handled
+- Fix lint
+- Update CI
diff --git a/e2e/checklist.md b/e2e/checklist.md
index 50e2c7125d560b2ae8b8491a764a4e18f806f478..5e740efa83d8e722ee51853383ce0ece19bb25da 100644
--- a/e2e/checklist.md
+++ b/e2e/checklist.md
@@ -48,6 +48,20 @@
   - [ ] v4 are visible
   - [ ] on hover, show correct region name(s)
   - [ ] whole mesh loads
+
+## Pt Assignments
+
+- [ ] human MNI152 julich brain should work (statistical)
+- [ ] rat waxholm v4 should work (labelled)
+- [ ] csv can be downloaded
+- [ ] big brain & fsaverage *shouldn't* work
+
+## Download atlas
+
+- [ ] human MNI152 julich brain can be downloaded
+- [ ] human MNI152 julich brain hoc1 left can be downloaded
+- [ ] rat waxholm v4 can be downloaded
+
 ## saneURL
 - [ ] saneurl generation functions properly
   - [ ] try existing key (human), and get unavailable error
diff --git a/mkdocs.yml b/mkdocs.yml
index df2d3dcc9969d727dc219a4a2450f0da70533330..fc88fe80be9e51f1591d52834ece4a8698b79ef5 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -33,6 +33,7 @@ nav:
     - Fetching datasets: 'advanced/datasets.md'
     - Display non-atlas volumes: 'advanced/otherVolumes.md'
   - Release notes:
+    - v2.11.2: 'releases/v2.11.2.md'
     - v2.11.1: 'releases/v2.11.1.md'
     - v2.11.0: 'releases/v2.11.0.md'
     - v2.10.3: 'releases/v2.10.3.md'
diff --git a/package-lock.json b/package-lock.json
index eaa6b864e66c3e6d3556f6482a0816e0eb9e5d0c..792fff775330a11e4a0c83b26158e1694e7836f7 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
 {
   "name": "siibra-explorer",
-  "version": "2.10.0",
+  "version": "2.11.2",
   "lockfileVersion": 3,
   "requires": true,
   "packages": {
     "": {
       "name": "siibra-explorer",
-      "version": "2.10.0",
+      "version": "2.11.2",
       "license": "apache-2.0",
       "dependencies": {
         "@angular/animations": "^14.2.12",
diff --git a/package.json b/package.json
index 9719e8ac3d423f69b3e79bc3c266675522175327..4ea49304574b3072c6f16f5690b98a624b3558ba 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "siibra-explorer",
-  "version": "2.11.1",
+  "version": "2.11.2",
   "description": "siibra-explorer - explore brain atlases. Based on humanbrainproject/nehuba & google/neuroglancer. Built with angular",
   "scripts": {
     "lint": "eslint src --ext .ts",
diff --git a/src/api/service.ts b/src/api/service.ts
index 6adceb099682923f5306647b857346dca23b1aa3..44520f13f9a2958437463fb45793a925ee5b5aec 100644
--- a/src/api/service.ts
+++ b/src/api/service.ts
@@ -172,7 +172,7 @@ const broadCastDefault: BroadCastingApiEvents = {
 
 export class ApiService implements BoothResponder<ApiBoothEvents>{
 
-  public broadcastCh = createBroadcastingJsonRpcChannel<`${NAMESPACE_TYPE}.on`, BroadCastingApiEvents>(`${namespace}.on`, broadCastDefault)
+  public broadcastCh = createBroadcastingJsonRpcChannel<`${NAMESPACE_TYPE}.on.`, BroadCastingApiEvents>(`${namespace}.on.`, broadCastDefault)
   public booth = new Booth<ApiBoothEvents>(this)
 
   private requestUserQueue: RequestUser<keyof RequestUserTypes>[] = []
@@ -263,27 +263,27 @@ export class ApiService implements BoothResponder<ApiBoothEvents>{
     this.store.pipe(
       select(atlasSelection.selectors.selectedAtlas)
     ).subscribe(atlas => {
-      this.broadcastCh.emit('atlasSelected', translateV3Entities.retrieveAtlas(atlas))
+      this.broadcastCh.emit('atlasSelected', atlas && translateV3Entities.retrieveAtlas(atlas))
     })
     this.store.pipe(
       select(atlasSelection.selectors.selectedParcellation)
     ).subscribe(parcellation => {
-      this.broadcastCh.emit('parcellationSelected', translateV3Entities.retrieveParcellation(parcellation))
+      this.broadcastCh.emit('parcellationSelected', parcellation && translateV3Entities.retrieveParcellation(parcellation))
     })
     this.store.pipe(
       select(atlasSelection.selectors.selectedTemplate)
     ).subscribe(template => {
-      this.broadcastCh.emit('templateSelected', translateV3Entities.retrieveTemplate(template))
+      this.broadcastCh.emit('templateSelected', template && translateV3Entities.retrieveTemplate(template))
     })
     this.store.pipe(
       select(atlasSelection.selectors.selectedRegions)
     ).subscribe(regions => {
-      this.broadcastCh.emit('regionsSelected', regions.map(reg => translateV3Entities.retrieveRegion(reg)))
+      this.broadcastCh.emit('regionsSelected', regions && regions.map(reg => translateV3Entities.retrieveRegion(reg)))
     })
     this.store.pipe(
       select(atlasSelection.selectors.selectedParcAllRegions)
     ).subscribe(regions => {
-      this.broadcastCh.emit('allRegions', regions.map(reg => translateV3Entities.retrieveRegion(reg)))
+      this.broadcastCh.emit('allRegions', regions && regions.map(reg => translateV3Entities.retrieveRegion(reg)))
     })
     this.store.pipe(
       select(atlasSelection.selectors.navigation)
diff --git a/src/atlasComponents/sapi/core/index.ts b/src/atlasComponents/sapi/core/index.ts
index a7fc4cbb696db25e9fa2159b5862e23c0bdb260e..ed68003d55ce542a35f5e173aaa173345202d597 100644
--- a/src/atlasComponents/sapi/core/index.ts
+++ b/src/atlasComponents/sapi/core/index.ts
@@ -1,4 +1,3 @@
 export { SAPIAtlas } from "./sapiAtlas"
-export { SAPISpace } from "./sapiSpace"
 export { SAPIParcellation } from "./sapiParcellation"
 export { SAPIRegion } from "./sapiRegion"
diff --git a/src/atlasComponents/sapi/core/sapiRegion.ts b/src/atlasComponents/sapi/core/sapiRegion.ts
index 0c5a2d0baf73fa0ba4d6e499abdbe4e3930eeb13..5c9db2f9fa82eed38c7c85afaebb57653bab0cee 100644
--- a/src/atlasComponents/sapi/core/sapiRegion.ts
+++ b/src/atlasComponents/sapi/core/sapiRegion.ts
@@ -1,7 +1,6 @@
 import { SAPI } from "..";
 import { SapiRegionModel, RouteParam } from "../typeV3";
-import { strToRgb, hexToRgb } from 'common/util'
-import { NEVER, Observable, of } from "rxjs";
+import { Observable, of } from "rxjs";
 import { map } from "rxjs/operators";
 import { SAPIBase } from "./base";
 import { SxplrRegion } from "../sxplrTypes";
@@ -92,16 +91,6 @@ export class SAPIRegion extends SAPIBase<RF>{
     )
   }
 
-  /**
-   * 
-   * @deprecated
-   * @param volumeId 
-   * @returns 
-   */
-  getVolumeInstance(volumeId: string): Observable<never> {
-    return NEVER
-  }
-
   getDetail(spaceId: string): Observable<SapiRegionModel> {
     return this.sapi.v3Get("/regions/{region_id}", {
       path: {
diff --git a/src/atlasComponents/sapi/core/sapiSpace.ts b/src/atlasComponents/sapi/core/sapiSpace.ts
deleted file mode 100644
index b19359e3cbc373699aa332abb3b06d424d7f0742..0000000000000000000000000000000000000000
--- a/src/atlasComponents/sapi/core/sapiSpace.ts
+++ /dev/null
@@ -1,65 +0,0 @@
-import { Observable, of, throwError } from "rxjs"
-import { SAPI } from '../sapi.service'
-import { SxplrTemplate } from "../sxplrTypes"
-import { map, switchMap } from "rxjs/operators"
-import { SAPIBase } from "./base"
-
-/**
- * All valid parcellation features
- */
-const SpaceFeatures = {
-  Image: "Image",
-} as const
-
-export type SF = keyof typeof SpaceFeatures
-
-type FeatureResponse = {
-  features: {
-    [key: string]: string
-  }
-}
-
-type RegionalSpatialFeatureOpts = {
-  parcellationId: string
-  region: string
-}
-
-type BBoxSpatialFEatureOpts = {
-  bbox: string
-}
-
-type SpatialFeatureOpts = RegionalSpatialFeatureOpts | BBoxSpatialFEatureOpts
-
-export class SAPISpace extends SAPIBase<SF>{
-
-  static Features$ = of(Object.keys(SpaceFeatures) as SF[])
-  public features$ = SAPISpace.Features$
-
-  constructor(private sapi: SAPI, public atlasId: string, public id: string){
-    super(sapi)
-    this.prefix$ = SAPI.BsEndpoint$.pipe(
-      map(endpt => `${endpt}/atlases/${encodeURIComponent(this.atlasId)}/spaces/${encodeURIComponent(this.id)}`)
-    )
-  }
-
-  private prefix$: Observable<string>
-
-  getModalities(): Observable<FeatureResponse> {
-    return this.prefix$.pipe(
-      switchMap(prefix => this.sapi.httpGet<FeatureResponse>(
-        `${prefix}/features`,
-        null,
-      ))
-    )
-  }
-
-  getDetail(): Observable<SxplrTemplate>{
-    return this.prefix$.pipe(
-      switchMap(prefix => this.sapi.httpGet<SxplrTemplate>(
-        `${prefix}`,
-        null,
-      ))
-    )
-  }
-
-}
diff --git a/src/atlasComponents/sapi/index.ts b/src/atlasComponents/sapi/index.ts
index 356276003c98cafb620eaf5aa67df35acffcff4b..2ec890861ec737a5a1aec4b1f6d4d899fac532c7 100644
--- a/src/atlasComponents/sapi/index.ts
+++ b/src/atlasComponents/sapi/index.ts
@@ -3,7 +3,6 @@ export { SAPIModule } from './module'
 export { SAPI } from "./sapi.service"
 export {
   SAPIAtlas,
-  SAPISpace,
   SAPIParcellation,
   SAPIRegion
 } from "./core"
diff --git a/src/atlasComponents/sapi/sapi.service.ts b/src/atlasComponents/sapi/sapi.service.ts
index 7959d63fbd7715d7be672d626e02ffaa77d68100..bf83652addca6154bc509ef4ce7b3c25e743f752 100644
--- a/src/atlasComponents/sapi/sapi.service.ts
+++ b/src/atlasComponents/sapi/sapi.service.ts
@@ -1,7 +1,7 @@
 import { Injectable } from "@angular/core";
 import { HttpClient } from '@angular/common/http';
 import { catchError, map, shareReplay, switchMap, take, tap } from "rxjs/operators";
-import { getExportNehuba } from "src/util/fn";
+import { getExportNehuba, noop } from "src/util/fn";
 import { MatSnackBar } from "@angular/material/snack-bar";
 import { AtlasWorkerService } from "src/atlasViewer/atlasViewer.workerService.service";
 import { EnumColorMapName } from "src/util/colorMaps";
@@ -13,7 +13,6 @@ import {
 import { FeatureType, PathReturn, RouteParam, SapiRoute } from "./typeV3";
 import { BoundingBox, SxplrAtlas, SxplrParcellation, SxplrRegion, SxplrTemplate, VoiFeature, Feature } from "./sxplrTypes";
 import { parcBanList, speciesOrder } from "src/util/constants";
-import { IDS } from "./constants";
 
 export const useViewer = {
   THREESURFER: "THREESURFER",
@@ -22,7 +21,7 @@ export const useViewer = {
 } as const
 
 export const SIIBRA_API_VERSION_HEADER_KEY='x-siibra-api-version'
-export const EXPECTED_SIIBRA_API_VERSION = '0.3.4'
+export const EXPECTED_SIIBRA_API_VERSION = '0.3.5'
 
 let BS_ENDPOINT_CACHED_VALUE: Observable<string> = null
 
@@ -111,8 +110,7 @@ export class SAPI{
               .then(flag => {
                 if (flag) rs(endpt)
               })
-              // eslint-disable-next-line  @typescript-eslint/no-empty-function
-              .catch(e => {})
+              .catch(noop)
           }
         })
         try {
@@ -351,7 +349,7 @@ export class SAPI{
             template.id,
             "LABELLED"
           ).pipe(
-            catchError((err, obs) => of(null as SxplrParcellation)),
+            catchError(() => of(null as SxplrParcellation)),
             map(_map => _map && parc)
           )
         )
@@ -429,7 +427,7 @@ export class SAPI{
             space.id,
             "LABELLED"
           ).pipe(
-            catchError((err, obs) => of(null as SxplrTemplate)),
+            catchError(() => of(null as SxplrTemplate)),
             map(_map => _map && space)
           )
         )
@@ -520,7 +518,7 @@ export class SAPI{
       //     continue
       //   }
       // }
-      for (const { volume: volumeIdx, fragment, label } of map.indices[regionname]) {
+      for (const { volume: volumeIdx, fragment } of map.indices[regionname]) {
         const { providedVolumes } = map.volumes[volumeIdx]
         if (!("neuroglancer/precomputed" in providedVolumes)) {
           continue
diff --git a/src/atlasComponents/sapi/schemaV3.ts b/src/atlasComponents/sapi/schemaV3.ts
index e73a25736e182902ac13528a75848ee3a6f44e3c..3c10d79b9c849d9aa745879549de94cfe82b45fa 100644
--- a/src/atlasComponents/sapi/schemaV3.ts
+++ b/src/atlasComponents/sapi/schemaV3.ts
@@ -642,12 +642,6 @@ export interface components {
        */
       ontologyIdentifier?: (string)[]
     }
-    /**
-     * ImageTypes 
-     * @description An enumeration. 
-     * @enum {unknown}
-     */
-    ImageTypes: "BlockfaceVolumeOfInterest" | "CellBodyStainedVolumeOfInterest" | "CellbodyStainedSection" | "MRIVolumeOfInterest" | "PLIVolumeOfInterest" | "SegmentedVolumeOfInterest" | "XPCTVolumeOfInterest"
     /** LocationModel */
     LocationModel: {
       /** @Type */
@@ -1237,12 +1231,6 @@ export interface components {
       /** Max */
       max: number
     }
-    /**
-     * TabularTypes 
-     * @description An enumeration. 
-     * @enum {unknown}
-     */
-    TabularTypes: "ReceptorDensityFingerprint" | "LayerwiseBigBrainIntensities" | "LayerwiseCellDensity" | "RegionalBOLD"
     /** ValidationError */
     ValidationError: {
       /** Location */
@@ -1677,6 +1665,7 @@ export interface operations {
         parcellation_id: string
         space_id: string
         point: string
+        assignment_type?: string
         sigma_mm?: number
       }
     }
@@ -1902,7 +1891,7 @@ export interface operations {
       query: {
         parcellation_id: string
         region_id: string
-        type?: components["schemas"]["TabularTypes"]
+        type?: string
         page?: number
         size?: number
       }
@@ -1928,7 +1917,7 @@ export interface operations {
       query: {
         parcellation_id: string
         region_id: string
-        type?: components["schemas"]["TabularTypes"]
+        type?: string
       }
       path: {
         feature_id: string
@@ -1955,7 +1944,7 @@ export interface operations {
       query: {
         space_id: string
         bbox?: string
-        type?: components["schemas"]["ImageTypes"]
+        type?: string
         page?: number
         size?: number
       }
@@ -1980,7 +1969,7 @@ export interface operations {
     parameters: {
       query: {
         space_id: string
-        type?: components["schemas"]["ImageTypes"]
+        type?: string
       }
       path: {
         feature_id: string
diff --git a/src/atlasComponents/sapi/sxplrTypes.ts b/src/atlasComponents/sapi/sxplrTypes.ts
index ef556f25eb9c77344aa826d7b6d88e1e478c1227..95860602d584abe68740c2bbe9a5a4018e5e8641 100644
--- a/src/atlasComponents/sapi/sxplrTypes.ts
+++ b/src/atlasComponents/sapi/sxplrTypes.ts
@@ -102,10 +102,6 @@ export type Feature = {
   category?: string
 } & Partial<AdditionalInfo>
 
-type DataFrame = {
-  index: Record<string, string>
-}
-
 export type VoiFeature = {
   bbox: BoundingBox
   ngVolume: {
diff --git a/src/atlasComponents/sapi/translateV3.ts b/src/atlasComponents/sapi/translateV3.ts
index e92c14d9fe61a46e14b7bb4be99a1541c8e39ec8..da87a784b79e7d07e4b6848bbba43de822dc2138 100644
--- a/src/atlasComponents/sapi/translateV3.ts
+++ b/src/atlasComponents/sapi/translateV3.ts
@@ -40,7 +40,7 @@ class TranslateV3 {
   }
   async translateParcellation(parcellation:PathReturn<"/parcellations/{parcellation_id}">): Promise<SxplrParcellation> {
     const ds = await Promise.all((parcellation.datasets || []).map(ds => this.translateDs(ds)))
-    const { name, ...rest } = ds[0] || {}
+    const { ...rest } = ds[0] || {}
     const { ['@id']: prevId } = parcellation.version?.prev || {}
     return {
       id: parcellation["@id"],
@@ -147,7 +147,7 @@ class TranslateV3 {
     for (const defaultImage of validImages) {
       
       const { providedVolumes } = defaultImage
-      const { "neuroglancer/precomputed": precomputedVol, ...rest } = await this.#extractNgPrecompUnfrag(providedVolumes)
+      const { "neuroglancer/precomputed": precomputedVol } = await this.#extractNgPrecompUnfrag(providedVolumes)
       
       if (!precomputedVol) {
         console.error(`neuroglancer/precomputed data source has not been found!`)
diff --git a/src/atlasComponents/sapi/typeV3.ts b/src/atlasComponents/sapi/typeV3.ts
index d65db66debe2bff385851d785213cec40749b3c5..22fdbcfe328e20fec2328f648be5baae4e1aa615 100644
--- a/src/atlasComponents/sapi/typeV3.ts
+++ b/src/atlasComponents/sapi/typeV3.ts
@@ -1,4 +1,4 @@
-import { components, paths, operations } from "./schemaV3"
+import { components, paths } from "./schemaV3"
 
 export type SapiAtlasModel = PathReturn<"/atlases/{atlas_id}">
 export type SapiSpaceModel = PathReturn<"/spaces/{space_id}">
@@ -22,6 +22,7 @@ type _FeatureType<FeatureRoute extends SapiRoute> = FeatureRoute extends `/featu
     ? never
     : FT extends "{feature_id}"
       ? never
+      // eslint-disable-next-line @typescript-eslint/no-unused-vars
       : FT extends `${infer _FT}/{${infer _FID}}`
         ? never
         : FT
diff --git a/src/atlasComponents/sapiViews/core/parcellation/module.ts b/src/atlasComponents/sapiViews/core/parcellation/module.ts
index 1dba15a672f32048508569aa03b9a63f9e96fed0..9fb7e0066b8d71826f96e61a38e88ad5e3157a6c 100644
--- a/src/atlasComponents/sapiViews/core/parcellation/module.ts
+++ b/src/atlasComponents/sapiViews/core/parcellation/module.ts
@@ -1,9 +1,7 @@
 import { CommonModule } from "@angular/common";
-import { APP_INITIALIZER, NgModule } from "@angular/core";
-import { Store } from "@ngrx/store";
+import { NgModule } from "@angular/core";
 import { ComponentsModule } from "src/components";
 import { AngularMaterialModule } from "src/sharedModules";
-import { atlasAppearance } from "src/state";
 import { StrictLocalModule } from "src/strictLocal";
 import { DialogModule } from "src/ui/dialogInfo/module";
 import { UtilModule } from "src/util";
@@ -14,6 +12,8 @@ import { ParcellationDoiPipe } from "./parcellationDoi.pipe";
 import { ParcellationVisibilityService } from "./parcellationVis.service";
 import { ParcellationGroupSelectedPipe } from "./parcellationGroupSelected.pipe";
 import { IsGroupedParcellation } from "./isGroupedParcellation.pipe";
+import { EffectsModule } from "@ngrx/effects";
+import { ParcellationVisEffect } from "./parcellationVis.effect";
 
 @NgModule({
   imports: [
@@ -23,7 +23,10 @@ import { IsGroupedParcellation } from "./isGroupedParcellation.pipe";
     UtilModule,
     SapiViewsUtilModule,
     DialogModule,
-    StrictLocalModule
+    StrictLocalModule,
+    EffectsModule.forFeature([
+      ParcellationVisEffect
+    ])
   ],
   declarations: [
     FilterGroupedParcellationPipe,
@@ -41,21 +44,6 @@ import { IsGroupedParcellation } from "./isGroupedParcellation.pipe";
   ],
   providers: [
     ParcellationVisibilityService,
-    {
-      provide: APP_INITIALIZER,
-      useFactory: (store: Store, svc: ParcellationVisibilityService) => {
-        svc.visibility$.subscribe(val => {
-          store.dispatch(
-            atlasAppearance.actions.setShowDelineation({
-              flag: val
-            })
-          )
-        })
-        return () => Promise.resolve()
-      },
-      multi: true,
-      deps: [ Store, ParcellationVisibilityService ]
-    }
   ]
 })
 
diff --git a/src/atlasComponents/sapiViews/core/parcellation/parcellationVis.effect.ts b/src/atlasComponents/sapiViews/core/parcellation/parcellationVis.effect.ts
new file mode 100644
index 0000000000000000000000000000000000000000..bc8d7765ba35cf9ed4fda375bc50bfaf36284ffa
--- /dev/null
+++ b/src/atlasComponents/sapiViews/core/parcellation/parcellationVis.effect.ts
@@ -0,0 +1,14 @@
+import { Injectable } from "@angular/core";
+import { ParcellationVisibilityService } from "./parcellationVis.service";
+import { createEffect } from "@ngrx/effects";
+import { map } from "rxjs/operators";
+import { atlasAppearance } from "src/state";
+
+@Injectable()
+export class ParcellationVisEffect {
+  onEmitToggleDelineation = createEffect(() => this.svc.visibility$.pipe(
+    map(flag => atlasAppearance.actions.setShowDelineation({ flag }))
+  ))
+
+  constructor(private svc: ParcellationVisibilityService){}
+}
diff --git a/src/atlasComponents/sapiViews/core/region/module.ts b/src/atlasComponents/sapiViews/core/region/module.ts
index 9482528706f278dc726d6a17f8096ac82fed2328..6e9140d0b5968e384f4f08907246dd6b9a621a30 100644
--- a/src/atlasComponents/sapiViews/core/region/module.ts
+++ b/src/atlasComponents/sapiViews/core/region/module.ts
@@ -9,7 +9,6 @@ import { StrictLocalModule } from "src/strictLocal";
 import { SapiViewsUtilModule } from "../../util/module";
 import { SapiViewsCoreRegionRegionListItem } from "./region/listItem/region.listItem.component";
 import { SapiViewsCoreRegionRegionBase } from "./region/region.base.directive";
-import { SapiViewsCoreRegionRegionalFeatureDirective } from "./region/region.features.directive";
 import { SapiViewsCoreRegionRegionRich } from "./region/rich/region.rich.component";
 
 @NgModule({
@@ -27,13 +26,11 @@ import { SapiViewsCoreRegionRegionRich } from "./region/rich/region.rich.compone
     SapiViewsCoreRegionRegionListItem,
     SapiViewsCoreRegionRegionRich,
     SapiViewsCoreRegionRegionBase,
-    SapiViewsCoreRegionRegionalFeatureDirective,
   ],
   exports: [
     SapiViewsCoreRegionRegionListItem,
     SapiViewsCoreRegionRegionRich,
     SapiViewsCoreRegionRegionBase,
-    SapiViewsCoreRegionRegionalFeatureDirective,
   ]
 })
 
diff --git a/src/atlasComponents/sapiViews/core/region/region/region.base.directive.ts b/src/atlasComponents/sapiViews/core/region/region/region.base.directive.ts
index a2204a080335eb69d7644bf8c383eb4fb3d643f4..59b09ba91bb2e0eddbac28add6ed03fdd4c0cade 100644
--- a/src/atlasComponents/sapiViews/core/region/region/region.base.directive.ts
+++ b/src/atlasComponents/sapiViews/core/region/region/region.base.directive.ts
@@ -1,4 +1,4 @@
-import { Directive, EventEmitter, Input, Output, SimpleChanges } from "@angular/core";
+import { Directive, EventEmitter, Input, Output } from "@angular/core";
 import { SxplrAtlas, SxplrParcellation, SxplrRegion, SxplrTemplate } from "src/atlasComponents/sapi/sxplrTypes";
 import { translateV3Entities } from "src/atlasComponents/sapi/translateV3"
 import { rgbToHsl } from 'common/util'
@@ -72,7 +72,7 @@ export class SapiViewsCoreRegionRegionBase {
     map(([ atp, region ]) => ({ ...atp, region }))
   )
 
-  ngOnChanges(sc: SimpleChanges): void {
+  ngOnChanges(): void {
     const { atlas, template, parcellation } = this
     this.ATP$.next({ atlas, template, parcellation })
   }
@@ -97,7 +97,7 @@ export class SapiViewsCoreRegionRegionBase {
        */
       const rgb = SAPIRegion.GetDisplayColor(this.region) || [200, 200, 200]
       this.regionRgbString = `rgb(${rgb.join(',')})`
-      const [_h, _s, l] = rgbToHsl(...rgb)
+      const [ /* _h */, /* _s */, l] = rgbToHsl(...rgb)
       this.regionDarkmode = l < 0.4
       
       /**
diff --git a/src/atlasComponents/sapiViews/core/region/region/region.features.directive.ts b/src/atlasComponents/sapiViews/core/region/region/region.features.directive.ts
deleted file mode 100644
index b7019d477953329a64fb471ad620b4f7486b059f..0000000000000000000000000000000000000000
--- a/src/atlasComponents/sapiViews/core/region/region/region.features.directive.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-import { Directive, OnChanges, SimpleChanges } from "@angular/core";
-import { BehaviorSubject, merge, NEVER } from "rxjs";
-import { switchMap,  filter, startWith, shareReplay, scan } from "rxjs/operators";
-import { SAPI, SAPIRegion } from "src/atlasComponents/sapi";
-import { SxplrAtlas, SxplrParcellation, SxplrTemplate, SxplrRegion } from "src/atlasComponents/sapi/sxplrTypes"
-import { SapiViewsCoreRegionRegionBase } from "./region.base.directive";
-
-@Directive({
-  selector: '[sxplr-sapiviews-core-region-regional-feature]',
-  exportAs: 'sapiViewsRegionalFeature'
-})
-
-export class SapiViewsCoreRegionRegionalFeatureDirective extends SapiViewsCoreRegionRegionBase implements OnChanges{
-
-  constructor(sapi: SAPI){
-    super(sapi)
-  }
-
-  private features$ = NEVER
-
-  public listOfFeatures$ = this.features$.pipe(
-    startWith([]),
-    shareReplay(1),
-  )
-
-  public busy$ = new BehaviorSubject<boolean>(false)
-}
diff --git a/src/atlasComponents/sapiViews/core/region/region/rich/region.rich.component.ts b/src/atlasComponents/sapiViews/core/region/region/rich/region.rich.component.ts
index 9db77ddb32c2077ff94f932785ffc5469a50b6a3..c61d33b9d2c25cd406383ed85cc437f6364748ca 100644
--- a/src/atlasComponents/sapiViews/core/region/region/rich/region.rich.component.ts
+++ b/src/atlasComponents/sapiViews/core/region/region/rich/region.rich.component.ts
@@ -28,8 +28,6 @@ export class SapiViewsCoreRegionRegionRich extends SapiViewsCoreRegionRegionBase
   @Output('sxplr-sapiviews-core-region-region-rich-feature-clicked')
   featureClicked = new EventEmitter<Feature>()
 
-  public expandedPanel: string
-
   constructor(
     sapi: SAPI,
     @Inject(DARKTHEME) public darktheme$: Observable<boolean>,
@@ -41,16 +39,6 @@ export class SapiViewsCoreRegionRegionRich extends SapiViewsCoreRegionRegionBase
     this.featureClicked.emit(feat)
   }
 
-  // eslint-disable-next-line  @typescript-eslint/no-empty-function
-  handleExpansionPanelClosedEv(title: string){
-    this.expandedPanel = null
-  }
-
-  // eslint-disable-next-line  @typescript-eslint/no-empty-function
-  handleExpansionPanelAfterExpandEv(title: string) {
-    this.expandedPanel = title
-  }
-
   activePanelTitles$: Observable<string[]> = new Subject()
 
   private regionalStatisticalMaps$ = this.ATPR$.pipe(
diff --git a/src/atlasComponents/sapiViews/core/rich/ATPSelector/wrapper/wrapper.component.ts b/src/atlasComponents/sapiViews/core/rich/ATPSelector/wrapper/wrapper.component.ts
index 6a8a8b546078f57907c0d7bf03bb8443f8d1bcb0..9f60eadca5c1111ad2ace1a72818e2ac8520feec 100644
--- a/src/atlasComponents/sapiViews/core/rich/ATPSelector/wrapper/wrapper.component.ts
+++ b/src/atlasComponents/sapiViews/core/rich/ATPSelector/wrapper/wrapper.component.ts
@@ -4,7 +4,7 @@ import { select, Store } from "@ngrx/store";
 import { Observable, of, Subject, Subscription } from "rxjs";
 import { filter, map, switchMap, tap, withLatestFrom } from "rxjs/operators";
 import { SAPI } from "src/atlasComponents/sapi/sapi.service";
-import { atlasSelection } from "src/state";
+import { atlasAppearance, atlasSelection } from "src/state";
 import { fromRootStore } from "src/state/atlasSelection";
 import { DialogFallbackCmp } from "src/ui/dialogInfo";
 import { DARKTHEME } from "src/util/injectionTokens";
@@ -16,11 +16,6 @@ function isATPGuard(obj: any): obj is Partial<ATP&{ requested: Partial<ATP> }> {
   return (obj.atlas || obj.template || obj.parcellation) && (!obj.requested || isATPGuard(obj.requested))
 }
 
-const banListParcName = new Set([
-  "VEP Atlas",
-  "Desikan-Killiany 2006"
-])
-
 @Component({
   selector: 'sxplr-wrapper-atp-selector',
   templateUrl: './wrapper.template.html',
@@ -60,7 +55,9 @@ export class WrapperATPSelector implements OnDestroy{
   )
   isBusy$ = new Subject<boolean>()
   
-  parcellationVisibility$ = this.svc.visibility$
+  parcellationVisibility$ = this.store$.pipe(
+    select(atlasAppearance.selectors.showDelineation)
+  )
 
   constructor(
     private dialog: MatDialog,
diff --git a/src/atlasComponents/sapiViews/volumes/point-assignment/point-assignment.component.html b/src/atlasComponents/sapiViews/volumes/point-assignment/point-assignment.component.html
index 57a9cf3d5031587bc37f7ac36e115319b396f500..59694f74a9f84f067a93a56eb0f0d9988895d8e1 100644
--- a/src/atlasComponents/sapiViews/volumes/point-assignment/point-assignment.component.html
+++ b/src/atlasComponents/sapiViews/volumes/point-assignment/point-assignment.component.html
@@ -1,7 +1,13 @@
-<div class="sxplr-m-2" *ngIf="busy$ | async">
+<div class="sxplr-m-2" *ngIf="busy$ | async as busyMessage">
     <spinner-cmp class="sxplr-d-inline-block"></spinner-cmp>
     <span>
-        Performing probabilistic assignment ...
+        {{ busyMessage }}
+    </span>
+</div>
+
+<div class="sxplr-m-2" *ngIf="error$ | async">
+    <span>
+        An error occurred when performing map assignment.
     </span>
 </div>
 
diff --git a/src/atlasComponents/sapiViews/volumes/point-assignment/point-assignment.component.ts b/src/atlasComponents/sapiViews/volumes/point-assignment/point-assignment.component.ts
index 90cf9b9ed7aaca875eec919e4a718e6a6ef66898..64b0ebdb1a71bdbf9baf0d0d4c687df6afa71cae 100644
--- a/src/atlasComponents/sapiViews/volumes/point-assignment/point-assignment.component.ts
+++ b/src/atlasComponents/sapiViews/volumes/point-assignment/point-assignment.component.ts
@@ -1,15 +1,18 @@
-import { Component, Input, OnDestroy, Output, TemplateRef, EventEmitter, ViewChild, AfterViewInit } from '@angular/core';
+import { Component, Input, OnDestroy, Output, TemplateRef, EventEmitter } from '@angular/core';
 import { MatDialog } from '@angular/material/dialog';
 import { BehaviorSubject, EMPTY, Observable, Subscription, combineLatest, concat, of } from 'rxjs';
-import { map, shareReplay, switchMap, tap } from 'rxjs/operators';
+import { catchError, map, shareReplay, switchMap, tap } from 'rxjs/operators';
 import { SAPI, EXPECTED_SIIBRA_API_VERSION } from 'src/atlasComponents/sapi/sapi.service';
 import { SxplrParcellation, SxplrRegion, SxplrTemplate } from 'src/atlasComponents/sapi/sxplrTypes';
 import { translateV3Entities } from 'src/atlasComponents/sapi/translateV3';
 import { PathReturn } from 'src/atlasComponents/sapi/typeV3';
-import { TSandsPoint } from 'src/util/types';
+import { TFace, TSandsPoint } from 'src/util/types';
 import { TZipFileConfig } from "src/zipFilesOutput/type"
 import { environment } from "src/environments/environment"
 
+const DOING_PROB_ASGMT = "Performing probabilistic assignment ..."
+const DOING_LABEL_ASGMT = "Probabilistic assignment failed. Performing labelled assignment ..."
+
 @Component({
   selector: 'sxplr-point-assignment',
   templateUrl: './point-assignment.component.html',
@@ -22,12 +25,19 @@ export class PointAssignmentComponent implements OnDestroy {
     "map value",
   ]
   
-  #busy$ = new BehaviorSubject(false)
+  #busy$ = new BehaviorSubject<string>(null)
   busy$ = this.#busy$.asObservable()
 
+  #error$ = new BehaviorSubject<string>(null)
+  error$ = this.#error$.asObservable()
+
   #point = new BehaviorSubject<TSandsPoint>(null)
   @Input()
-  set point(val: TSandsPoint) {
+  set point(val: TSandsPoint|TFace) {
+    const { '@type': type } = val
+    if (type === "siibra-explorer/surface/face") {
+      return
+    }
     this.#point.next(val)
   }
   
@@ -52,6 +62,9 @@ export class PointAssignmentComponent implements OnDestroy {
     this.#template,
   ]).pipe(
     switchMap(([ point, parcellation, template ]) => {
+
+      this.#error$.next(null)
+
       if (!point || !parcellation || !template) {
         return EMPTY
       }
@@ -60,7 +73,7 @@ export class PointAssignmentComponent implements OnDestroy {
         console.warn(`point coordination space id ${ptSpaceId} is not the same as template id ${template.id}.`)
         return EMPTY
       }
-      this.#busy$.next(true)
+      this.#busy$.next(DOING_PROB_ASGMT)
       return concat(
         of(null),
         this.sapi.v3Get("/map/assign", {
@@ -71,7 +84,24 @@ export class PointAssignmentComponent implements OnDestroy {
             sigma_mm: 0
           }
         }).pipe(
-          tap(() => this.#busy$.next(false)),
+          catchError(() => {
+            this.#busy$.next(DOING_LABEL_ASGMT)
+            return this.sapi.v3Get("/map/assign", {
+              query: {
+                parcellation_id: parcellation.id,
+                point: point.coordinates.map(v => `${v.value/1e6}mm`).join(','),
+                space_id: template.id,
+                sigma_mm: 0,
+                assignment_type: "labelled"
+              }
+            })
+          }),
+          catchError((err) => {
+            this.#busy$.next(null)
+            this.#error$.next(err.toString())
+            return of(null)
+          }),
+          tap(() => this.#busy$.next(null)),
         )
       )
     }),
@@ -118,7 +148,7 @@ export class PointAssignmentComponent implements OnDestroy {
 function generateReadMe(pt: TSandsPoint, parc: SxplrParcellation, tmpl: SxplrTemplate){
   return `# Point assignment exporter
 
-Exported by siibra-explorer verison \`${environment.VERSION}\` hash: \`${environment.GIT_HASH}\`.
+Exported by siibra-explorer verison \`${environment.VERSION}\` hash: \`${environment.GIT_HASH.trim()}\`.
 
 On: ${new Date().toString()}
 
diff --git a/src/atlasComponents/userAnnotations/module.ts b/src/atlasComponents/userAnnotations/module.ts
index ec2586e5741ddc2d25ff4c45657154d882386946..f6c3d1682f6979a7fa2446a5f2a67c658f66d722 100644
--- a/src/atlasComponents/userAnnotations/module.ts
+++ b/src/atlasComponents/userAnnotations/module.ts
@@ -54,7 +54,7 @@ import { RoutedAnnotationService } from "./routedAnnotation.service";
     // ... in url correctly
     {
       provide: APP_INITIALIZER,
-      useFactory:(svc: RoutedAnnotationService) => {
+      useFactory:(_svc: RoutedAnnotationService) => {
         return () => Promise.resolve()
       },
       deps: [ RoutedAnnotationService ],
diff --git a/src/atlasComponents/userAnnotations/singleAnnotationUnit/singleAnnotationUnit.component.ts b/src/atlasComponents/userAnnotations/singleAnnotationUnit/singleAnnotationUnit.component.ts
index 15bfc561e3f86608e4b18f0de67970d1391d8af5..09895109507b4eb9baf2283557cabd45ca7a59bc 100644
--- a/src/atlasComponents/userAnnotations/singleAnnotationUnit/singleAnnotationUnit.component.ts
+++ b/src/atlasComponents/userAnnotations/singleAnnotationUnit/singleAnnotationUnit.component.ts
@@ -44,7 +44,7 @@ export class SingleAnnotationUnit implements OnDestroy, AfterViewInit{
 
     this.chSubs.push(
       this.formGrp.valueChanges.subscribe(value => {
-        const { name, desc, spaceId } = value
+        const { name, desc } = value
         this.managedAnnotation.name = name
         this.managedAnnotation.desc = desc
       })
diff --git a/src/atlasComponents/userAnnotations/tools/delete.ts b/src/atlasComponents/userAnnotations/tools/delete.ts
index 2e118bcd3dddb46ab2aa8d6ce702b8b14ccdd054..be375acbc193ad1a6ec52e11c33ea75ee934fa4a 100644
--- a/src/atlasComponents/userAnnotations/tools/delete.ts
+++ b/src/atlasComponents/userAnnotations/tools/delete.ts
@@ -2,7 +2,7 @@ import { Directive, OnDestroy } from "@angular/core";
 import { Observable, Subject, Subscription } from "rxjs";
 import { filter, switchMapTo, takeUntil, withLatestFrom } from "rxjs/operators";
 import { Point } from "./point";
-import { AbsToolClass, IAnnotationEvents, IAnnotationGeometry, IAnnotationTools, TAnnotationEvent, TCallbackFunction, TNgAnnotationPoint, TToolType } from "./type";
+import { AbsToolClass, IAnnotationEvents, IAnnotationGeometry, IAnnotationTools, TAnnotationEvent, TCallbackFunction, TToolType } from "./type";
 
 @Directive()
 export class ToolDelete extends AbsToolClass<Point> implements IAnnotationTools, OnDestroy {
diff --git a/src/atlasComponents/userAnnotations/tools/point.ts b/src/atlasComponents/userAnnotations/tools/point.ts
index a2e10804108682e14e844481094063cfac3fad5c..58d8cdde8acd05863e682814e37f8d667124e36e 100644
--- a/src/atlasComponents/userAnnotations/tools/point.ts
+++ b/src/atlasComponents/userAnnotations/tools/point.ts
@@ -1,4 +1,4 @@
-import { AbsToolClass, getCoord, IAnnotationEvents, IAnnotationGeometry, IAnnotationTools, INgAnnotationTypes, TAnnotationEvent, TBaseAnnotationGeomtrySpec, TCallbackFunction, TNgAnnotationEv, TSandsPoint, TToolType } from "./type";
+import { AbsToolClass, getCoord, IAnnotationEvents, IAnnotationGeometry, IAnnotationTools, INgAnnotationTypes, TAnnotationEvent, TBaseAnnotationGeomtrySpec, TCallbackFunction, TSandsPoint, TToolType } from "./type";
 import { Observable, Subject, Subscription } from "rxjs";
 import { Directive, OnDestroy } from "@angular/core";
 import { filter, switchMapTo, takeUntil } from "rxjs/operators";
diff --git a/src/atlasComponents/userAnnotations/tools/poly.ts b/src/atlasComponents/userAnnotations/tools/poly.ts
index 37a0fdbd397fe43fa136409af1503a2cb2443bbe..244c71a6a2d11163ba70af11727adcefd1ac399f 100644
--- a/src/atlasComponents/userAnnotations/tools/poly.ts
+++ b/src/atlasComponents/userAnnotations/tools/poly.ts
@@ -1,7 +1,7 @@
-import { IAnnotationTools, IAnnotationGeometry, TAnnotationEvent, IAnnotationEvents, AbsToolClass, INgAnnotationTypes, TNgAnnotationEv, TToolType, TBaseAnnotationGeomtrySpec, TSandsPolyLine, getCoord, TCallbackFunction } from "./type";
+import { IAnnotationTools, IAnnotationGeometry, TAnnotationEvent, IAnnotationEvents, AbsToolClass, INgAnnotationTypes, TToolType, TBaseAnnotationGeomtrySpec, TSandsPolyLine, getCoord, TCallbackFunction } from "./type";
 import { Point, TPointJsonSpec } from './point'
 import { Directive, OnDestroy } from "@angular/core";
-import { merge, Observable, Subject, Subscription } from "rxjs";
+import { Observable, Subject, Subscription } from "rxjs";
 import { filter, switchMapTo, takeUntil, withLatestFrom } from "rxjs/operators";
 import { getUuid } from "src/util/fn";
 
@@ -129,7 +129,7 @@ export class Polygon extends IAnnotationGeometry{
   }
 
   parseNgAnnotationObj(pickedAnnotationId: string, pickedOffset: number): { edge: [number, number], edgeIdx: number, point: Point, pointIdx: number } {
-    const [ id, edgeIdx, _shouldBeZero ] = pickedAnnotationId.split('_')
+    const [ id, edgeIdx, /* _shouldBeZero */ ] = pickedAnnotationId.split('_')
     if (id !== this.id) return null
 
     if (pickedOffset === 0) {
diff --git a/src/atlasComponents/userAnnotations/tools/select.ts b/src/atlasComponents/userAnnotations/tools/select.ts
index 10befd2dfe4b65ade055f2fcc81d57af5e2d4d3b..3653d86efb003f7676018b6adf53a5d7b40c80ef 100644
--- a/src/atlasComponents/userAnnotations/tools/select.ts
+++ b/src/atlasComponents/userAnnotations/tools/select.ts
@@ -2,7 +2,7 @@ import { Directive, OnDestroy } from "@angular/core";
 import { Observable, Subject, Subscription } from "rxjs";
 import { filter } from 'rxjs/operators'
 import { Point } from "./point";
-import { AbsToolClass, IAnnotationEvents, IAnnotationGeometry, IAnnotationTools, TAnnotationEvent, TCallbackFunction, TNgAnnotationPoint, TToolType } from "./type";
+import { AbsToolClass, IAnnotationEvents, IAnnotationGeometry, IAnnotationTools, TAnnotationEvent, TCallbackFunction, TToolType } from "./type";
 
 @Directive()
 export class ToolSelect extends AbsToolClass<Point> implements IAnnotationTools, OnDestroy {
diff --git a/src/atlasComponents/userAnnotations/tools/service.ts b/src/atlasComponents/userAnnotations/tools/service.ts
index 4a18bd4f3dc806ea1bef95f1f6339a17b63f6ead..03f0f060e620f05897e380044ef381bea50c5c71 100644
--- a/src/atlasComponents/userAnnotations/tools/service.ts
+++ b/src/atlasComponents/userAnnotations/tools/service.ts
@@ -6,7 +6,7 @@ import { BehaviorSubject, combineLatest, fromEvent, merge, Observable, of, Subje
 import {map, switchMap, filter, shareReplay, pairwise, withLatestFrom } from "rxjs/operators";
 import { NehubaViewerUnit } from "src/viewerModule/nehuba";
 import { NEHUBA_INSTANCE_INJTKN } from "src/viewerModule/nehuba/util";
-import { AbsToolClass, ANNOTATION_EVENT_INJ_TOKEN, IAnnotationEvents, IAnnotationGeometry, INgAnnotationTypes, INJ_ANNOT_TARGET, TAnnotationEvent, ClassInterface, TCallbackFunction, TSands, TGeometryJson, TNgAnnotationLine, TCallback } from "./type";
+import { AbsToolClass, ANNOTATION_EVENT_INJ_TOKEN, IAnnotationEvents, IAnnotationGeometry, INgAnnotationTypes, INJ_ANNOT_TARGET, TAnnotationEvent, ClassInterface, TCallbackFunction, TSands, TGeometryJson, TCallback } from "./type";
 import { getExportNehuba, switchMapWaitFor } from "src/util/fn";
 import { Polygon } from "./poly";
 import { Line } from "./line";
@@ -194,7 +194,7 @@ export class ModularUserAnnotationToolService implements OnDestroy{
   }): AbsToolClass<any>{
     const { toolCls: Cls, target, editCmp } = arg
     const newTool = new Cls(this.annotnEvSubj, arg => this.handleToolCallback(arg)) as T & { ngOnDestroy?: () => void }
-    const { name, iconClass, onMouseMoveRenderPreview } = newTool
+    const { name, iconClass } = newTool
     
     this.moduleAnnotationTypes.push({
       instance: newTool,
diff --git a/src/atlasViewer/atlasViewer.component.ts b/src/atlasViewer/atlasViewer.component.ts
index 9255c9065120627b7998d0c9c297972a69f1c0ff..c28d15f9a80133259294b4de407a543014adcf78 100644
--- a/src/atlasViewer/atlasViewer.component.ts
+++ b/src/atlasViewer/atlasViewer.component.ts
@@ -18,7 +18,7 @@ import { colorAnimation } from "./atlasViewer.animation"
 import { MouseHoverDirective } from "src/mouseoverModule";
 import {MatSnackBar, MatSnackBarRef} from "@angular/material/snack-bar";
 import {MatDialog, MatDialogRef} from "@angular/material/dialog";
-import { ARIA_LABELS, CONST } from 'common/constants'
+import { CONST } from 'common/constants'
 
 import { SlServiceService } from "src/spotlight/sl-service.service";
 import { ClickInterceptorService } from "src/glue";
@@ -28,12 +28,6 @@ import { userPreference } from "src/state"
 import { DARKTHEME } from "src/util/injectionTokens";
 import { EnumQuickTourSeverity } from "src/ui/quickTour/constrants";
 
-/**
- * TODO
- * check against auxlillary mesh indicies, to only filter out aux indicies
- */
-const filterFn = (segment) => typeof segment.segment !== 'string'
-const compareFn = (it, item) => it.name === item.name
 
 @Component({
   selector: 'atlas-viewer',
@@ -49,7 +43,6 @@ const compareFn = (it, item) => it.name === item.name
 export class AtlasViewer implements OnDestroy, OnInit, AfterViewInit {
 
   public CONST = CONST
-  public compareFn = compareFn
 
   @ViewChild('cookieAgreementComponent', {read: TemplateRef}) public cookieAgreementComponent: TemplateRef<any>
 
diff --git a/src/atlasViewer/atlasViewer.workerService.service.ts b/src/atlasViewer/atlasViewer.workerService.service.ts
index 67a422714822d25e47fdb55b345116cda9db8eba..32d6c3b05e767da8b43d6c019f3c7e440cdae729 100644
--- a/src/atlasViewer/atlasViewer.workerService.service.ts
+++ b/src/atlasViewer/atlasViewer.workerService.service.ts
@@ -34,7 +34,7 @@ export class AtlasWorkerService {
     ).toPromise()
 
     const { data: returnData } = message as MessageEvent
-    const { id, error, ...rest } = returnData
+    const { error, ...rest } = returnData
     if (error) {
       throw new Error(error.message || error)
     }
diff --git a/src/components/fabSpeedDial/fabSpeedDialContainer.directive.ts b/src/components/fabSpeedDial/fabSpeedDialContainer.directive.ts
index 2c5967a634ff77bd08cf6b46a920afdd6fc51c74..321e5f9bc6f52dbb1289af7ea04db2084d5a341d 100644
--- a/src/components/fabSpeedDial/fabSpeedDialContainer.directive.ts
+++ b/src/components/fabSpeedDial/fabSpeedDialContainer.directive.ts
@@ -1,4 +1,4 @@
-import { Directive, OnDestroy, Output, EventEmitter, Input, OnChanges, SimpleChanges, HostListener, ElementRef, HostBinding } from "@angular/core";
+import { Directive, OnDestroy, Output, EventEmitter, Input, OnChanges, SimpleChanges, HostBinding } from "@angular/core";
 import { FabSpeedDialService } from "./fabSpeedDial.service";
 import { Subscription } from "rxjs";
 import { SCALE_ORIGIN } from './fabSpeedDial.service'
diff --git a/src/components/flatHierarchy/spacer.pipe.ts b/src/components/flatHierarchy/spacer.pipe.ts
index a7533b68c759ed72c1a56b87a762409a4d8a5f2b..73498906a0e6aa52ac93a16027c59e20f30b7c0d 100644
--- a/src/components/flatHierarchy/spacer.pipe.ts
+++ b/src/components/flatHierarchy/spacer.pipe.ts
@@ -7,7 +7,7 @@ import { TreeNode } from "./const"
 })
 
 export class FlatHierarchySpacer implements PipeTransform{
-  public transform<T>(inputNode: TreeNode<T>, ...args: any[]) {
+  public transform<T>(inputNode: TreeNode<T>, ..._args: any[]) {
     return Array(inputNode.level).fill(null)
   }
 }
diff --git a/src/components/flatHierarchy/treeView/treeControl.ts b/src/components/flatHierarchy/treeView/treeControl.ts
index 7471dfbb839cb36c23413d026c2f9c8f607af6dd..d8676d4ff1b7840994f9ac12bebed0ab5c8d8e31 100644
--- a/src/components/flatHierarchy/treeView/treeControl.ts
+++ b/src/components/flatHierarchy/treeView/treeControl.ts
@@ -13,7 +13,7 @@ export class Tree<T extends Record<string, unknown>>{
     return this._nodes
   }
 
-  private _isParent: IsParent<T> = (c, p) => false
+  private _isParent: IsParent<T> = (_c, _p) => false
   protected set isParent(fn: IsParent<T>){
     if (fn === this._isParent) return
     this._isParent = fn
@@ -81,7 +81,7 @@ export class Tree<T extends Record<string, unknown>>{
 
   constructor(
     _nodes: T[] = [],
-    _isParent: IsParent<T> = (c, p) => false
+    _isParent: IsParent<T> = (_c, _p) => false
   ){
     this._nodes = _nodes
     this._isParent = _isParent
diff --git a/src/components/markdown/markdownCmp/markdown.component.ts b/src/components/markdown/markdownCmp/markdown.component.ts
index 7084626a5ed37fb4162d610edfe232fcf3852381..fd6776dec0c312e74c659bff8fb4668e2fbf130a 100644
--- a/src/components/markdown/markdownCmp/markdown.component.ts
+++ b/src/components/markdown/markdownCmp/markdown.component.ts
@@ -1,4 +1,4 @@
-import { ChangeDetectionStrategy, Component, ElementRef, Input, ViewChild, ChangeDetectorRef, AfterViewChecked, OnChanges, SecurityContext } from '@angular/core'
+import { ChangeDetectionStrategy, Component, ElementRef, Input, ViewChild, ChangeDetectorRef, OnChanges, SecurityContext } from '@angular/core'
 import { DomSanitizer } from '@angular/platform-browser'
 import * as showdown from 'showdown'
 
diff --git a/src/components/parseAttribute.directive.ts b/src/components/parseAttribute.directive.ts
deleted file mode 100644
index 34a9b124841c32106a8f590f00d80d69f85d337b..0000000000000000000000000000000000000000
--- a/src/components/parseAttribute.directive.ts
+++ /dev/null
@@ -1,75 +0,0 @@
-import { Directive, OnChanges, SimpleChanges } from "@angular/core";
-
-// TODO deprecate this directive
-function parseAttribute(arg: any, expectedType: string) {
-
-  // if(
-  //   typeof arg === expectedType ||
-  //   arg === undefined ||
-  //   arg === null
-  // ){
-  //   return arg
-  // }
-  // switch (expectedType){
-  //   case 'object':
-  //     try{
-  //       const json =  JSON.parse(arg)
-  //       return json
-  //     }catch(e){
-  //       this.log.warn('parseAttribute error, cannot JSON.parse object')
-  //       return arg
-  //     }
-  //   case 'boolean' :
-  //     return arg === 'true'
-  //   case 'number':
-  //     return isNaN(arg) ? 0 : Number(arg)
-
-  //   case 'string':
-  //   default :
-  //     return arg
-  // }
-
-  /* return if empty string */
-  if (
-    arg === '' ||
-    arg === undefined ||
-    arg === null
-  ) {
-    return arg
-  }
-
-  if (!isNaN(arg)) {
-    return Number(arg)
-  }
-
-  if (arg === 'true') {
-    return true
-  }
-
-  if (arg === 'false') {
-    return false
-  }
-
-  try {
-    const json = JSON.parse(arg)
-    return json
-  } catch (e) {
-    // this.log.warn('parseAttribute, parse JSON, not a json')
-    /* not a json, continue */
-    /* probably print in debug mode */
-  }
-
-  return arg
-}
-
-@Directive({
-  selector : '[ivparseattribute]',
-})
-
-export class ParseAttributeDirective implements OnChanges {
-  public ngOnChanges(simpleChanges: SimpleChanges) {
-    Object.keys(simpleChanges).forEach(key => {
-      this[key] = parseAttribute(simpleChanges[key].currentValue, typeof simpleChanges[key].previousValue)
-    })
-  }
-}
diff --git a/src/components/smartChip/component/smartChip.component.ts b/src/components/smartChip/component/smartChip.component.ts
index b68cfb42769e31067b42614351e8db04717fdcf7..99eed11983dd317c32c5f4875e93f640caf8bf95 100644
--- a/src/components/smartChip/component/smartChip.component.ts
+++ b/src/components/smartChip/component/smartChip.component.ts
@@ -13,12 +13,12 @@ const cssColorToHsl = (input: string) => {
       parseInt(match[2]),
       parseInt(match[3]),
     ]
-    const [_h, _s, l] = rgbToHsl(...rgb)
+    const [ /* _h */, /* _s */, l] = rgbToHsl(...rgb)
     return l
   }
   if (/hsl/i.test(input)) {
     const match = /\((.*)\)/.exec(input)
-    const [h, s, l] = match[1].split(",")
+    const [ /* _h */, /* _s */, l] = match[1].split(",")
     const trimmedL = l.trim()
     if (/%$/.test(trimmedL)) {
       const match = /^([0-9]+)%/.exec(trimmedL)
@@ -27,7 +27,7 @@ const cssColorToHsl = (input: string) => {
   }
   if (/^#/i.test(input) && input.length === 7) {
     const [r, g, b] = hexToRgb(input)
-    const [_h, _s, l] = rgbToHsl(r, g, b)
+    const [ /*_h */, /*_s */, l] = rgbToHsl(r, g, b)
     return l
   }
   throw new Error(`Cannot parse css color: ${input}`)
diff --git a/src/features/connectivity/connectivityBrowser/connectivityBrowser.component.ts b/src/features/connectivity/connectivityBrowser/connectivityBrowser.component.ts
index f4a2c8e6231db8386047195264206516136d8577..77b69d99dccae4d04870b68d7ac6a223b59548df 100644
--- a/src/features/connectivity/connectivityBrowser/connectivityBrowser.component.ts
+++ b/src/features/connectivity/connectivityBrowser/connectivityBrowser.component.ts
@@ -1,7 +1,7 @@
 import {  Component, ElementRef, OnDestroy, ViewChild, Input, SimpleChanges, HostListener, OnChanges } from "@angular/core";
 import { Store, select} from "@ngrx/store";
 import { Subscription, BehaviorSubject, combineLatest, merge, concat, NEVER} from "rxjs";
-import { switchMap, map, tap, shareReplay, distinctUntilChanged, withLatestFrom, filter, finalize } from "rxjs/operators";
+import { switchMap, map, shareReplay, distinctUntilChanged, withLatestFrom, filter, finalize } from "rxjs/operators";
 
 import { atlasAppearance, atlasSelection } from "src/state";
 import { SAPI } from "src/atlasComponents/sapi/sapi.service";
diff --git a/src/features/entry/entry.component.ts b/src/features/entry/entry.component.ts
index 722fd8e99735fb88a04ab0435c6a0bccaa760306..610af8724d495501def8df5fc6ead5e761f9b17f 100644
--- a/src/features/entry/entry.component.ts
+++ b/src/features/entry/entry.component.ts
@@ -14,7 +14,7 @@ import { TranslatedFeature } from '../list/list.directive';
 const categoryAcc = <T extends Record<string, unknown>>(categories: T[]) => {
   const returnVal: Record<string, T[]> = {}
   for (const item of categories) {
-    const { category, ...rest } = item
+    const { category } = item
     if (!category) continue
     if (typeof category !== "string") continue
     if (!returnVal[category]) {
@@ -128,7 +128,6 @@ export class EntryComponent extends FeatureBase implements AfterViewInit, OnDest
                 await ds.pull()
               } catch (e) {
                 if (e instanceof DsExhausted) {
-                  console.log('exhausted')
                   break
                 }
                 if (e instanceof IsAlreadyPulling ) {
diff --git a/src/index.html b/src/index.html
index c1cef937495c9ed9218e6ec90326307b07a8816e..1ed2d8187899e51442bc39c8ab9305ac15c7ea0f 100644
--- a/src/index.html
+++ b/src/index.html
@@ -14,7 +14,7 @@
   <script src="extra_js.js"></script>
   <script src="https://unpkg.com/kg-dataset-previewer@1.2.0/dist/kg-dataset-previewer/kg-dataset-previewer.js" defer></script>
   <script src="https://unpkg.com/three-surfer@0.0.13/dist/bundle.js" defer></script>
-  <script type="module" src="https://unpkg.com/ng-layer-tune@0.0.12/dist/ng-layer-tune/ng-layer-tune.esm.js"></script>
+  <script type="module" src="https://unpkg.com/ng-layer-tune@0.0.13/dist/ng-layer-tune/ng-layer-tune.esm.js"></script>
   <script type="module" src="https://unpkg.com/hbp-connectivity-component@0.6.6/dist/connectivity-component/connectivity-component.js" ></script>
   <script defer src="https://unpkg.com/mathjax@3.1.2/es5/tex-svg.js"></script>
   <script defer src="https://unpkg.com/d3@6.2.0/dist/d3.min.js"></script>
diff --git a/src/keyframesModule/keyframeCtrl/keyframeCtrl.component.ts b/src/keyframesModule/keyframeCtrl/keyframeCtrl.component.ts
index 6f909d5280166c3544c8f3ec81ed0610db49fa88..1b39b366a26ad75ffd55b1a2af12fc78679dd20e 100644
--- a/src/keyframesModule/keyframeCtrl/keyframeCtrl.component.ts
+++ b/src/keyframesModule/keyframeCtrl/keyframeCtrl.component.ts
@@ -171,13 +171,11 @@ export class KeyFrameCtrlCmp implements OnDestroy {
         )
 
         const startVec = vec1.clone()
-        const vec1Length = vec1.length()
         const vec2 = new THREE.Vector3(
           toPayloadCamera.x,
           toPayloadCamera.y,
           toPayloadCamera.z,
         )
-        const vec2Length = vec2.length()
         vec1.normalize()
         vec2.normalize()
 
diff --git a/src/messaging/nmvSwc/index.ts b/src/messaging/nmvSwc/index.ts
index d7bd4d6a767d013e2e357cb98d79202a7ecfed08..87e4b10ef6a82fee3b44926a4e7e02684274433c 100644
--- a/src/messaging/nmvSwc/index.ts
+++ b/src/messaging/nmvSwc/index.ts
@@ -86,12 +86,6 @@ const getAtlas = (spaceId: SPACE_ID) => {
   return DEFAULT_ATLAS[spaceId]
 }
 
-const getVoxelFromSpace = (spaceId: string) => {
-  for (const key in NM_IDS){
-    if (NM_IDS[key] === spaceId) return IAV_VOXEL_SIZES_NM[key]
-  }
-  return null
-}
 
 export const processJsonLd = (json: { [key: string]: any }): Observable<IMessagingActions<keyof IMessagingActionTmpl>> => {
   const subject = new Subject<IMessagingActions<keyof IMessagingActionTmpl>>()
@@ -156,27 +150,16 @@ export const processJsonLd = (json: { [key: string]: any }): Observable<IMessagi
     )
     const uuid = getUuid()
 
-    // NG internal treats skeleton as mm
-    const voxelSize = getVoxelFromSpace(toSpace)
-    /**
-     * swc seem to scale with voxelSize... strangely enough
-     * voxelSize nm / voxel -> goal is 1 voxel/um
-     * 1e3 / voxelSize
-     */
-    const scaleUmToVoxelFixed = [
-      voxelSize[0],
-      voxelSize[1],
-      voxelSize[2],
-    ]
     // NG translation works on nm scale
     const scaleUmToNm = 1e3
     const modA = mat3.fromValues(
-      scaleUmToVoxelFixed[0], 0, 0,
-      0, scaleUmToVoxelFixed[1], 0,
-      0, 0, scaleUmToVoxelFixed[2]
+      scaleUmToNm, 0, 0,
+      0, scaleUmToNm, 0,
+      0, 0, scaleUmToNm
     )
     mat3.mul(modA, modA, [...A[0], ...A[1], ...A[2]])
-    const modb = vec3.scale(vec3.create(), b, scaleUmToNm)
+    const modb = vec3.mul(vec3.create(), b, [ scaleUmToNm, scaleUmToNm, scaleUmToNm])
+    vec3.scale(vec3.create(), b, scaleUmToNm)
     const transform = [
       [...modA.slice(0, 3), modb[0]] as TVec4,
       [...modA.slice(3, 6), modb[1]] as TVec4,
diff --git a/src/messaging/service.spec.ts b/src/messaging/service.spec.ts
index 8ba8cad4e3cdaf0d776fd5ff2f1e1cc0958c8b08..05da2a3999f7c350a304b3fca3e997029bec624e 100644
--- a/src/messaging/service.spec.ts
+++ b/src/messaging/service.spec.ts
@@ -1,5 +1,5 @@
 import { TestBed } from "@angular/core/testing"
-import { MockStore, provideMockStore } from "@ngrx/store/testing"
+import { provideMockStore } from "@ngrx/store/testing"
 import { AtlasWorkerService } from "src/atlasViewer/atlasViewer.workerService.service"
 import { AngularMaterialModule } from "src/sharedModules"
 import { getUuid } from "src/util/fn"
@@ -9,6 +9,7 @@ import { MANAGED_METHODS } from './service'
 import { of, Subject } from "rxjs"
 import { ConfirmDialogComponent } from "src/components/confirmDialog/confirmDialog.component"
 import { TYPE as NATIVE_TYPE } from './native'
+import { ApiService } from "src/api"
 
 describe('> service.ts', () => {
   describe('> MessagingService', () => {
@@ -34,6 +35,17 @@ describe('> service.ts', () => {
           {
             provide: WINDOW_MESSAGING_HANDLER_TOKEN,
             useValue: windowMessagehandler
+          },
+          {
+            provide: ApiService,
+            useValue: {
+              booth: {
+                handshake(){}
+              },
+              broadcastCh: {
+                addListener(){}
+              }
+            }
           }
         ]
       })
@@ -118,7 +130,7 @@ describe('> service.ts', () => {
         it('> pong', async () => {
           const result = await mService.handleMessage({
             data: {
-              method: `${IAV_POSTMESSAGE_NAMESPACE}ping`
+              method: `ping`
             },
             origin: 'foobar'
           })
diff --git a/src/messaging/service.ts b/src/messaging/service.ts
index 365a2d1880bd4513bb088b49ff0b761faa30b36c..3abdeb901b8c1a2f713e1eb4bdb1cef5a38fac27 100644
--- a/src/messaging/service.ts
+++ b/src/messaging/service.ts
@@ -1,29 +1,44 @@
 import { Inject, Injectable, Optional } from "@angular/core";
 import { Observable } from "rxjs";
 import { MatDialog } from "@angular/material/dialog";
-import { MatSnackBar } from "@angular/material/snack-bar";
-
-import { getUuid } from "src/util/fn";
-import { AtlasWorkerService } from "src/atlasViewer/atlasViewer.workerService.service";
+import { getUuid, noop } from "src/util/fn";
 import { ConfirmDialogComponent } from "src/components/confirmDialog/confirmDialog.component";
 
 import { IMessagingActions, IMessagingActionTmpl, WINDOW_MESSAGING_HANDLER_TOKEN, IWindowMessaging } from './types'
 import { TYPE as NMV_TYPE, processJsonLd as nmvProcess } from './nmvSwc/index'
 import { TYPE as NATIVE_TYPE, processJsonLd as nativeProcess } from './native'
+import { BoothVisitor, JRPCRequest, ListenerChannel } from "src/api/jsonrpc"
+import { ApiService } from "src/api";
+import { ApiBoothEvents, namespace as apiNameSpace } from "src/api/service";
 
 export const IAV_POSTMESSAGE_NAMESPACE = `ebrains:iav:`
 
+const RECOGNISED_NAMESPACES = [
+  IAV_POSTMESSAGE_NAMESPACE,
+  apiNameSpace
+]
+
 export const MANAGED_METHODS = [
   'openminds:nmv:loadSwc',
   'openminds:nmv:unloadSwc'
 ]
 
+class WindowOpenerListener implements ListenerChannel {
+  constructor(
+    public registerLeaveCb: () => void,
+    public notify: (payload: JRPCRequest<unknown, unknown>) => void
+  ){}
+  
+}
+
 @Injectable({
   providedIn: 'root'
 })
 
 export class MessagingService {
 
+  private originListenerMap = new Map<string, {listener: WindowOpenerListener, visitor: BoothVisitor<ApiBoothEvents>}>()
+
   private whiteListedOrigins = new Set()
   private pendingRequests: Map<string, Promise<boolean>> = new Map()
   private windowName: string
@@ -32,8 +47,7 @@ export class MessagingService {
   
   constructor(
     private dialog: MatDialog,
-    private snackbar: MatSnackBar,
-    private worker: AtlasWorkerService,
+    private apiService: ApiService,
     @Optional() @Inject(WINDOW_MESSAGING_HANDLER_TOKEN) private messagingHandler: IWindowMessaging,
   ){
     
@@ -59,12 +73,45 @@ export class MessagingService {
     }
 
     window.addEventListener('message', async ({ data, origin, source }) => {
+      
+      /**
+       * only deal with opener
+       */
+      if (!window.opener || source !== window.opener) {
+        return
+      }
+
       if (/^webpack/.test(data.type)) return
-      if (data === '') return
+      if (!data) return
+      const { method } = data
+      if (RECOGNISED_NAMESPACES.every(namespace => (method || '').indexOf(namespace) !== 0)) {
+        return
+      }
       const src = source as Window
       const { id } = data
       try {
         const result = await this.handleMessage({ data, origin })
+        if (!this.originListenerMap.has(origin)) {
+          const listener = new WindowOpenerListener(
+            noop,
+            val => src.postMessage(val, origin)
+          )
+          
+          const visitor = this.apiService.booth.handshake()
+          this.originListenerMap.set(origin, {listener, visitor})
+
+          this.apiService.broadcastCh.addListener(listener)
+          
+
+          /**
+           * if result was not yet populated, try populating it with 
+           * siibra-explorer api
+           */
+        }
+        if (!result) {
+          const { visitor } = this.originListenerMap.get(origin)
+          return await visitor.request(data)
+        }
         src.postMessage({
           id,
           jsonrpc: '2.0',
@@ -94,27 +141,25 @@ export class MessagingService {
 
   public async handleMessage({ data, origin }) {
     const { method, param } = data
-    
-    if (!method) return
-    if (method.indexOf(IAV_POSTMESSAGE_NAMESPACE) !== 0) return
-    const strippedMethod = method.replace(IAV_POSTMESSAGE_NAMESPACE, '')
-
     /**
      * if ping method, respond pong method
      */
-    if (strippedMethod === 'ping') {
+    if (method === 'ping') {
       return 'pong'
     }
 
     /**
      * otherwise, check permission
      */
-
     const allow = await this.checkOrigin({ origin })
     if (!allow) throw ({
       code: 403,
       message: 'User declined'
     })
+    
+    if (!method) return
+    if (method.indexOf(IAV_POSTMESSAGE_NAMESPACE) !== 0) return
+    const strippedMethod = method.replace(IAV_POSTMESSAGE_NAMESPACE, '')
 
     // TODO 
     // in future, check if in managed_methods
@@ -169,50 +214,11 @@ export class MessagingService {
     // TODO combine api service and messaging service into one
     // and implement it properly
 
-    // if (method === 'viewerHandle:add3DLandmarks') {
-    //   this.apiService.interactiveViewer.viewerHandle.add3DLandmarks(param)
-    //   return 'OK'
-    // }
-
-    // if (method === 'viewerHandle:remove3DLandmarks') {
-    //   this.apiService.interactiveViewer.viewerHandle.remove3DLandmarks(param)
-    //   return 'OK'
-    // }
-
-    /**
-     * TODO use loadResource in the future
-     */
-    if (method === '_tmp:plotly') {
-      const isLoadingSnack = this.snackbar.open(`Loading plotly mesh ...`)
-      const resp = await this.worker.sendMessage({
-        method: `PROCESS_PLOTLY`,
-        param
-      })
-      isLoadingSnack?.dismiss()
-      const meshId = 'bobby'
-      /**
-       * TODO re-enable plotly VTK mesh
-       */
-      
-      // if (false) {
-      //   const { objectUrl, customFragmentColor } = resp.result || {}
-      //   this.loadMesh({
-      //     type: 'VTK',
-      //     id: meshId,
-      //     url: objectUrl,
-      //     customFragmentColor
-      //   })
-      // } else {
-      //   this.snackbar.open(`Error: loadMesh method not injected.`)
-      // }
-      return 'OK'
-    }
-
     if (MANAGED_METHODS.indexOf(method) >= 0) {
       return await this.processJsonld(param)
     }
 
-    throw ({ code: 404, message: 'Method not found' })
+    return
   }
 
   async checkOrigin({ origin }): Promise<boolean> {
diff --git a/src/mouseoverModule/type.ts b/src/mouseoverModule/type.ts
deleted file mode 100644
index 38033f903e9047b4164c90137564a19d0f75ae86..0000000000000000000000000000000000000000
--- a/src/mouseoverModule/type.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-import { TRegionSummary } from "src/util/siibraApiConstants/types";
-
-export type TMouseOverVtkLandmark = {
-  landmarkName: string
-}
\ No newline at end of file
diff --git a/src/plugin/plugin.module.ts b/src/plugin/plugin.module.ts
index 998ca4056ecbb7a069133b021bc3e0aab8605fdc..563a7d9dbb010c2e5654ff7631e1168098c52919 100644
--- a/src/plugin/plugin.module.ts
+++ b/src/plugin/plugin.module.ts
@@ -1,10 +1,9 @@
-import { CommonModule, DOCUMENT } from "@angular/common";
+import { CommonModule } from "@angular/common";
 import { HttpClientModule } from "@angular/common/http";
 import { NgModule } from "@angular/core";
 import { LoggingModule } from "src/logging";
 import { AngularMaterialModule } from "src/sharedModules";
 import { UtilModule } from "src/util";
-import { appendScriptFactory, APPEND_SCRIPT_TOKEN, removeScriptFactory, REMOVE_SCRIPT_TOKEN } from "src/util/constants";
 import { IFrameSrcPipe } from "./iframeSrc.pipe";
 import { PluginBannerUI } from "./pluginBanner/pluginBanner.component";
 import { PluginPortal } from "./pluginPortal/pluginPortal.component";
diff --git a/src/routerModule/routeStateTransform.service.spec.ts b/src/routerModule/routeStateTransform.service.spec.ts
index a341cdd6d405e275beedfd82a29c8f42ef3f36a5..2dee59c937f86923ca06f41c073aca2a22dcc0ba 100644
--- a/src/routerModule/routeStateTransform.service.spec.ts
+++ b/src/routerModule/routeStateTransform.service.spec.ts
@@ -6,6 +6,7 @@ import { DefaultUrlSerializer } from "@angular/router"
 import * as nehubaConfigService from "src/viewerModule/nehuba/config.service"
 import { atlasSelection, userInteraction } from "src/state"
 import { encodeNumber } from "./cipher"
+import { QuickHash } from "src/util/fn"
 
 const serializer = new DefaultUrlSerializer()
 
@@ -123,7 +124,7 @@ describe("> routeStateTransform.service.ts", () => {
         const altasObj = {"@id": 'foo-bar-a'}
         const templObj = {"@id": 'foo-bar-t'}
         const parcObj = {"@id": 'foo-bar-p'}
-        const regions = [{}]
+        const regions = [{'name': 'selected-region-1'}]
         const standAloneVolumes = []
         const navigation = null
 
@@ -181,9 +182,12 @@ describe("> routeStateTransform.service.ts", () => {
           
           const getRegionLabelIndicesSpy = sapi.getRegionLabelIndices as jasmine.Spy
           getRegionLabelIndicesSpy.and.resolveTo(labelIndex)
-
           const s = await svc.cvtStateToRoute(state as any)
-          expect(s).toContain(`r:${ngId}::${encodeNumber(labelIndex, { float: false })}`)
+          
+          expect(getParcNgId).not.toHaveBeenCalled()
+          expect(getRegionLabelIndicesSpy).not.toHaveBeenCalled()
+
+          expect(s).toContain(`rn:${QuickHash.GetHash(regions[0].name)}`)
         })
   
         it('> ngId containing expected value', async () => {
diff --git a/src/routerModule/routeStateTransform.service.ts b/src/routerModule/routeStateTransform.service.ts
index 1032448ec67ea1c9bf80d3f18f82f901bf7c6057..b01ac54beb7085b01ea548ac2de69b4d0a103fff 100644
--- a/src/routerModule/routeStateTransform.service.ts
+++ b/src/routerModule/routeStateTransform.service.ts
@@ -9,6 +9,7 @@ import { getParcNgId } from "src/viewerModule/nehuba/config.service";
 import { decodeToNumber, encodeNumber, encodeURIFull, separator } from "./cipher";
 import { TUrlAtlas, TUrlPathObj, TUrlStandaloneVolume } from "./type";
 import { decodePath, encodeId, decodeId, encodePath } from "./util";
+import { QuickHash } from "src/util/fn";
 
 @Injectable()
 export class RouteStateTransformSvc {
@@ -26,6 +27,7 @@ export class RouteStateTransformSvc {
     const selectedTemplateId = decodeId( RouteStateTransformSvc.GetOneAndOnlyOne(obj.t) )
     const selectedParcellationId = decodeId( RouteStateTransformSvc.GetOneAndOnlyOne(obj.p) )
     const selectedRegionIds = obj.r
+    const selectedRegionNames = obj.rn
     
     if (!selectedAtlasId || !selectedTemplateId || !selectedParcellationId) {
       return {}
@@ -60,7 +62,11 @@ export class RouteStateTransformSvc {
     const userViewer = await this.sapi.useViewer(selectedTemplate).toPromise()
     
     const selectedRegions = await (async () => {
-      if (!selectedRegionIds) return []
+      if (!selectedRegionIds && !selectedRegionNames) return []
+
+      if (selectedRegionNames && selectedRegionNames.length > 0) {
+        return allParcellationRegions.filter(region => selectedRegionNames.includes(QuickHash.GetHash(region.name)))
+      }
 
       /**
        * should account for 
@@ -268,16 +274,7 @@ export class RouteStateTransformSvc {
       }
     }
   
-    // encoding selected regions
-    let selectedRegionsString: string
-    if (selectedRegions.length === 1) {
-      const region = selectedRegions[0]
-      const labelIndex = await this.sapi.getRegionLabelIndices(selectedTemplate, selectedParcellation, region)
-      
-      const ngId = getParcNgId(selectedAtlas, selectedTemplate, selectedParcellation, region)
-      selectedRegionsString = `${ngId}::${encodeNumber(labelIndex, { float: false })}`
-    }
-    let routes: TUrlPathObj<string, TUrlAtlas<string>> | TUrlPathObj<string, TUrlStandaloneVolume<string>>
+    let routes: TUrlPathObj<string|string[], TUrlAtlas<string|string[]>> | TUrlPathObj<string, TUrlStandaloneVolume<string>>
     
     routes = {
       // for atlas
@@ -287,7 +284,8 @@ export class RouteStateTransformSvc {
       // for parcellation
       p: selectedParcellation && encodeId(selectedParcellation.id),
       // for regions
-      r: selectedRegionsString && encodeURIFull(selectedRegionsString),
+      // r: selectedRegionsString && encodeURIFull(selectedRegionsString),
+      rn: selectedRegions[0] && selectedRegions.map(r => QuickHash.GetHash(r.name)),
       // nav
       ['@']: cNavString,
       // showing dataset
diff --git a/src/routerModule/type.ts b/src/routerModule/type.ts
index 13205ad3e09e0969a8c419a5d9803b2883bc2de3..284b5e7a9441fd52be9281ad3dec5c749e390993 100644
--- a/src/routerModule/type.ts
+++ b/src/routerModule/type.ts
@@ -7,6 +7,7 @@ export type TUrlAtlas<T> = {
   t: T   // template
   p: T   // parcellation
   r?: T  // region selected
+  rn?: T
 }
 
 export type TUrlPlugin<T> = {
diff --git a/src/screenshot/screenshotCmp/screenshot.component.ts b/src/screenshot/screenshotCmp/screenshot.component.ts
index 9af9d6b90a7d60af3438b2784906918b6f74aab0..2ccb1da45087f34c917a7626827ae14759cd48db 100644
--- a/src/screenshot/screenshotCmp/screenshot.component.ts
+++ b/src/screenshot/screenshotCmp/screenshot.component.ts
@@ -2,7 +2,7 @@ import { Component, HostListener, Inject, OnDestroy, Output, EventEmitter, Optio
 import { MatDialog } from "@angular/material/dialog";
 import { MatSnackBar } from "@angular/material/snack-bar";
 import { combineLatest, Observable, Subject, Subscription } from "rxjs";
-import { distinctUntilChanged, map, mapTo, shareReplay, startWith, switchMap, switchMapTo, tap } from "rxjs/operators";
+import { distinctUntilChanged, map, mapTo, shareReplay, startWith, switchMap, switchMapTo } from "rxjs/operators";
 import { HANDLE_SCREENSHOT_PROMISE, TypeHandleScrnShotPromise } from "../util";
 import { getDateString } from 'common/util'
 import { getUuid } from "src/util/fn";
diff --git a/src/services/uiService.service.ts b/src/services/uiService.service.ts
index cc8774728fb1742e36722135960341c35f7c0599..2e6a580418690c4d3e1182aa352132d853189410 100644
--- a/src/services/uiService.service.ts
+++ b/src/services/uiService.service.ts
@@ -1,6 +1,6 @@
 import { Injectable } from "@angular/core";
 import {MatSnackBar, MatSnackBarConfig} from "@angular/material/snack-bar";
-import { MatDialog } from "@angular/material/dialog";
+import { MatDialog, MatDialogConfig } from "@angular/material/dialog";
 import { ActionDialog } from "src/ui/actionDialog/actionDialog.component";
 
 @Injectable({
@@ -18,7 +18,7 @@ export class UIService {
     return this.snackbar.open(message, actionBtnTxt, config)
   }
 
-  public showDialog(data, options){
+  public showDialog(data: unknown, options: MatDialogConfig){
     return this.dialog.open(ActionDialog, {
       ...options,
       data
diff --git a/src/share/saneUrl/saneUrl.component.spec.ts b/src/share/saneUrl/saneUrl.component.spec.ts
index 982ecb76fb47ca954a5da6c9f5c792c69f3118ba..f8a8d3f8f35b5855f5671dbc21ad16c9d8859f02 100644
--- a/src/share/saneUrl/saneUrl.component.spec.ts
+++ b/src/share/saneUrl/saneUrl.component.spec.ts
@@ -1,13 +1,14 @@
 import { TestBed, fakeAsync, tick, flush, ComponentFixture } from '@angular/core/testing'
 import { SaneUrl } from './saneUrl.component'
 import { By } from '@angular/platform-browser'
-import { BACKENDURL } from 'src/util/constants'
 import { NoopAnimationsModule } from '@angular/platform-browser/animations'
 import { SaneUrlSvc } from './saneUrl.service'
 import { AngularMaterialModule } from 'src/sharedModules'
 import { CUSTOM_ELEMENTS_SCHEMA, Directive } from '@angular/core'
 import { of, throwError } from 'rxjs'
 import { NotFoundError } from '../type'
+import { ReactiveFormsModule } from '@angular/forms'
+import { CommonModule } from '@angular/common'
 
 const inputCss = `input[aria-label="Custom link"]`
 const submitCss = `button[aria-label="Create custom link"]`
@@ -34,6 +35,7 @@ describe('> saneUrl.component.ts', () => {
         imports: [
           NoopAnimationsModule,
           AngularMaterialModule,
+          ReactiveFormsModule,
         ],
         providers: [
           {
diff --git a/src/share/saneUrl/saneUrl.component.ts b/src/share/saneUrl/saneUrl.component.ts
index f7fbed0ea2bb72dcb5500bcf3d2cec5623b51872..0ce99cce3b2ac0d5167380d9f4182455f2de36e5 100644
--- a/src/share/saneUrl/saneUrl.component.ts
+++ b/src/share/saneUrl/saneUrl.component.ts
@@ -1,6 +1,6 @@
 import { Component, OnDestroy, Input } from "@angular/core";
 import { Observable, merge, of, Subscription, BehaviorSubject, combineLatest } from "rxjs";
-import { startWith, mapTo, map, debounceTime, switchMap, catchError, shareReplay, filter, tap, takeUntil, distinctUntilChanged } from "rxjs/operators";
+import { startWith, mapTo, map, debounceTime, switchMap, catchError, shareReplay, filter, tap, distinctUntilChanged } from "rxjs/operators";
 import { UntypedFormControl } from "@angular/forms";
 import { ErrorStateMatcher } from "@angular/material/core";
 import { Clipboard } from "@angular/cdk/clipboard";
@@ -88,7 +88,7 @@ export class SaneUrl implements OnDestroy{
         ? of(false)
         : this.svc.getKeyVal(val).pipe(
           mapTo(false),
-          catchError((err, obs) => {
+          catchError((err) => {
             if (err instanceof NotFoundError) return of(true)
             return of(false)
           })
@@ -164,9 +164,7 @@ export class SaneUrl implements OnDestroy{
       this.customUrl.value,
       this.stateTobeSaved
     ).subscribe(
-      resp => {
-        this.savingProgress$.next(ESavingProgress.DONE)
-      },
+      () => this.savingProgress$.next(ESavingProgress.DONE),
       err => {
         this.customUrl.enable()
 
diff --git a/src/share/saneUrl/saneUrl.service.ts b/src/share/saneUrl/saneUrl.service.ts
index d78a8ac903089062ba3cc86ca009e627947f70c6..d838c72b83c63d084102e9327b93462821caa703 100644
--- a/src/share/saneUrl/saneUrl.service.ts
+++ b/src/share/saneUrl/saneUrl.service.ts
@@ -25,7 +25,7 @@ export class SaneUrlSvc implements IKeyValStore{
       `${this.saneUrlRoot}${key}`,
       { responseType: 'json' }
     ).pipe(
-      catchError((err, obs) => {
+      catchError((err) => {
         const { status } = err
         if (status === 404) {
           return throwError(new NotFoundError('Not found'))
diff --git a/src/state/index.ts b/src/state/index.ts
index 12adc4b974fb893cef495e9310a5b990966478d4..aa9964ec9c0a69f063874b6a8b65382a72e2025c 100644
--- a/src/state/index.ts
+++ b/src/state/index.ts
@@ -22,6 +22,7 @@ export {
 
 export * as generalActions from "./actions"
 
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
 function debug(reducer: ActionReducer<MainState>): ActionReducer<MainState> {
   return function(state, action) {
     console.log('state', state);
diff --git a/src/ui/actionDialog/actionDialog.component.ts b/src/ui/actionDialog/actionDialog.component.ts
index 0275f8cf576cf236cfe6878446347144412711c4..ced5d32d45c3de46755b1ff7af1f14b8331965b7 100644
--- a/src/ui/actionDialog/actionDialog.component.ts
+++ b/src/ui/actionDialog/actionDialog.component.ts
@@ -22,7 +22,7 @@ export class ActionDialog{
   constructor(
     @Optional() @Inject(MAT_DIALOG_DATA) data: any
   ){
-    const { config, content, template, actions = [] } = data || {}
+    const { config, content, actions = [] } = data || {}
     const { sameLine = false } = config || {}
 
     this.content = content
@@ -30,7 +30,4 @@ export class ActionDialog{
     this.actions = actions
   }
 
-  actionHandler(event: MouseEvent, action: IDialogAction){
-    // TODO fill in the actionHandler
-  }
-}
\ No newline at end of file
+}
diff --git a/src/ui/actionDialog/actionDialog.template.html b/src/ui/actionDialog/actionDialog.template.html
index 095b27ee6c147c69f53ac164bb7c3f865fd2a021..5388f69f0d10a0d887a2dce39164a273f1e200d5 100644
--- a/src/ui/actionDialog/actionDialog.template.html
+++ b/src/ui/actionDialog/actionDialog.template.html
@@ -28,8 +28,7 @@
     <button *ngSwitchCase="'mat-flat-button'"
       mat-flat-button
       [color]="action.color || 'default'"
-      [mat-dialog-close]="action.dismiss && action"
-      (click)="actionHandler($event, action)">
+      [mat-dialog-close]="action.dismiss && action">
       <ng-container *ngTemplateOutlet="textNodeTmpl; context: action"></ng-container>        
     </button>
 
@@ -37,8 +36,7 @@
     <button *ngSwitchCase="'mat-raised-button'"
       mat-raised-button
       [color]="action.color || 'default'"
-      [mat-dialog-close]="action.dismiss && action"
-      (click)="actionHandler($event, action)">
+      [mat-dialog-close]="action.dismiss && action">
       <ng-container *ngTemplateOutlet="textNodeTmpl; context: action"></ng-container>        
     </button>
 
@@ -46,8 +44,7 @@
     <button *ngSwitchCase="'mat-stroked-button'"
       mat-stroked-button
       [color]="action.color || 'default'"
-      [mat-dialog-close]="action.dismiss && action"
-      (click)="actionHandler($event, action)">
+      [mat-dialog-close]="action.dismiss && action">
       <ng-container *ngTemplateOutlet="textNodeTmpl; context: action"></ng-container>        
     </button>
 
@@ -55,8 +52,7 @@
     <button *ngSwitchDefault
       mat-button
       [color]="action.color || 'default'"
-      [mat-dialog-close]="action.dismiss && action"
-      (click)="actionHandler($event, action)">
+      [mat-dialog-close]="action.dismiss && action">
       <ng-container *ngTemplateOutlet="textNodeTmpl; context: action"></ng-container>    
     </button>
   </ng-container>
diff --git a/src/ui/config/module.ts b/src/ui/config/module.ts
index 55fcded2c2c01aa17ce1bdb3420dc2e6c9634e5e..751aa6f16aca850c8dc9fd3e951d5e1484ba87bb 100644
--- a/src/ui/config/module.ts
+++ b/src/ui/config/module.ts
@@ -1,7 +1,6 @@
 import { CommonModule } from "@angular/common";
 import { NgModule } from "@angular/core";
 import { LayoutModule } from "src/layouts/layout.module";
-import { PluginModule } from "src/plugin";
 import { AngularMaterialModule } from "src/sharedModules";
 import { ConfigComponent } from "./configCmp/config.component";
 
@@ -9,7 +8,6 @@ import { ConfigComponent } from "./configCmp/config.component";
   imports: [
     CommonModule,
     AngularMaterialModule,
-    // PluginModule,
     LayoutModule,
   ],
   declarations: [
diff --git a/src/ui/dialogInfo/const.ts b/src/ui/dialogInfo/const.ts
deleted file mode 100644
index 09aa80f6f979e24b8cd407ec54fcbdfa4c8d3154..0000000000000000000000000000000000000000
--- a/src/ui/dialogInfo/const.ts
+++ /dev/null
@@ -1 +0,0 @@
-import { InjectionToken } from "@angular/core";
diff --git a/src/ui/help/helpOnePager/helpOnePager.component.ts b/src/ui/help/helpOnePager/helpOnePager.component.ts
index 570072137ea77c542c3efb56a60a717063cbef64..d1298937d73f2a5483265cc92d043eafb96cc090 100644
--- a/src/ui/help/helpOnePager/helpOnePager.component.ts
+++ b/src/ui/help/helpOnePager/helpOnePager.component.ts
@@ -1,4 +1,3 @@
-import { MatDialog } from '@angular/material/dialog';
 import { Component } from "@angular/core";
 import { ARIA_LABELS } from 'common/constants'
 
diff --git a/src/ui/nehubaContainer/mobileOverlay/mobileOverlay.component.ts b/src/ui/nehubaContainer/mobileOverlay/mobileOverlay.component.ts
deleted file mode 100644
index 4948b3a38be2f43149491447ec4c79a33237ae36..0000000000000000000000000000000000000000
--- a/src/ui/nehubaContainer/mobileOverlay/mobileOverlay.component.ts
+++ /dev/null
@@ -1,332 +0,0 @@
-import { Component, ElementRef, EventEmitter, Input, OnDestroy, OnInit, Output, ViewChild, Inject, TemplateRef, ViewChildren, QueryList } from "@angular/core";
-import { combineLatest, concat, fromEvent, merge, Observable, of, Subject, BehaviorSubject } from "rxjs";
-import { filter, map, scan, switchMap, takeUntil, startWith, pairwise, tap, shareReplay, distinctUntilChanged, switchMapTo, reduce } from "rxjs/operators";
-import { clamp } from "src/util/generator";
-import { DOCUMENT } from "@angular/common";
-
-const TOUCHMOVE_THRESHOLD = 50
-const SUBMENU_IXOBS_CONFIG = {
-
-}
-
-export interface ITunableProp{
-  name: string
-  displayName?: string
-  values: string[]
-  selected?: any
-}
-
-@Component({
-  selector : 'mobile-overlay',
-  templateUrl : './mobileOverlay.template.html',
-  styleUrls : [
-    './mobileOverlay.style.css',
-  ],
-  styles : [
-    `
-div.active > span:before
-{
-  content: '\u2022';
-  width: 1em;
-  display: inline-block;
-  background:none;
-}
-div:not(.active) > span:before
-{
-  content : ' ';
-  width : 1em;
-  display: inline-block;
-}
-    `,
-  ],
-})
-
-export class MobileOverlay implements OnInit, OnDestroy {
-
-  @Input('iav-mobile-overlay-guide-tmpl')
-  public guideTmpl: TemplateRef<any>
-
-  @Input('iav-mobile-overlay-hide-ctrl-btn')
-  public hideCtrlBtn: boolean = false
-
-  @Input('iav-mobile-overlay-ctrl-btn-pos')
-  public ctrlBtnPosition: { left: string, top: string } = { left: '50%', top: '50%' }
-  
-  @Input() public tunableProperties: ITunableProp[] = []
-  
-  @Output() public tunablePropertySelected: EventEmitter<ITunableProp> = new EventEmitter()
-  @Output() public deltaValue: EventEmitter<{delta: number, selectedProp: ITunableProp}> = new EventEmitter()
-  @Output() public valueSelected: EventEmitter<{ value: string, selectedProp: ITunableProp }> = new EventEmitter()
-
-  @ViewChild('initiator', {read: ElementRef, static: true}) public initiator: ElementRef
-  @ViewChild('mobileMenuContainer', {read: ElementRef, static: true}) public menuContainer: ElementRef
-  @ViewChild('intersector', {read: ElementRef, static: true}) public intersector: ElementRef
-  @ViewChild('subMenuObserver', {read: ElementRef, static: false}) public subMenuIx: ElementRef
-  @ViewChild('setValueContainer', { read: ElementRef, static: false }) public setValueContainer?: ElementRef
-
-  private _onDestroySubject: Subject<boolean> = new Subject()
-
-  private _focusedProperties: ITunableProp
-  get focusedProperty() {
-    return this._focusedProperties
-      ? this._focusedProperties
-      : this.tunableProperties[0]
-  }
-  get focusedIndex() {
-    return this._focusedProperties
-      ? this.tunableProperties.findIndex(p => p === this._focusedProperties)
-      : 0
-  }
-
-  private initiatorSingleTouchStart$: Observable<any>
-
-  public showScreen$: Observable<boolean>
-  public showProperties$: Observable<boolean>
-  public showDelta$: Observable<boolean>
-  public showInitiator$: Observable<boolean>
-  private _drag$: Observable<any>
-  private _thresholdDrag$: Observable<any>
-  private intersectionObserver: IntersectionObserver
-  private subMenuIxObs: IntersectionObserver
-
-  constructor(
-    @Inject(DOCUMENT) private document: Document
-  ){
-
-  }
-
-  public ngOnDestroy() {
-    this._onDestroySubject.next(true)
-    this._onDestroySubject.complete()
-    this.intersectionObserver && this.intersectionObserver.disconnect()
-    this.subMenuIxObs && this.subMenuIxObs.disconnect()
-  }
-
-  public ngOnInit() {
-
-    this.initiatorSingleTouchStart$ = fromEvent(this.initiator.nativeElement, 'touchstart').pipe(
-      filter((ev: TouchEvent) => ev.touches.length === 1),
-      shareReplay(1)
-    )
-
-    const itemCount = this.tunableProperties.length
-
-    const config = {
-      root: this.intersector.nativeElement,
-      threshold: [...[...Array(itemCount)].map((_, k) => k / itemCount), 1],
-    }
-
-    this.intersectionObserver = new IntersectionObserver((arg) => {
-      if (arg[0].isIntersecting) {
-        const ratio = arg[0].intersectionRatio - (1 / this.tunableProperties.length / 2)
-        this.focusItemIndex = this.tunableProperties.length - Math.round(ratio * this.tunableProperties.length) - 1
-      }
-    }, config)
-
-    this.intersectionObserver.observe(this.menuContainer.nativeElement)
-
-    this._drag$ = fromEvent(this.document, 'touchmove').pipe(
-      filter((ev: TouchEvent) => ev.touches.length === 1),
-      takeUntil(fromEvent(this.document, 'touchend').pipe(
-        filter((ev: TouchEvent) => ev.touches.length === 0),
-      )),
-    )
-
-    this._thresholdDrag$ = this._drag$.pipe(
-      distinctUntilChanged((o, n) => {
-        const deltaX = o.touches[0].screenX - n.touches[0].screenX
-        const deltaY = o.touches[0].screenY - n.touches[0].screenY
-        return (deltaX ** 2 + deltaY ** 2) < TOUCHMOVE_THRESHOLD
-      }),
-    )
-
-    this.showProperties$ = this.initiatorSingleTouchStart$.pipe(
-      switchMap(() => concat(
-        this._thresholdDrag$.pipe(
-          pairwise(),
-          map(double => ({
-            deltaX : double[1].touches[0].screenX - double[0].touches[0].screenX,
-            deltaY : double[1].touches[0].screenY - double[0].touches[0].screenY,
-          })),
-          map(v => v.deltaY ** 2 > v.deltaX ** 2),
-          scan((acc, _curr) => acc),
-        ),
-        of(false)
-      )),
-      startWith(false),
-      distinctUntilChanged(),
-      shareReplay(1)
-    )
-
-    this.showDelta$ = this.initiatorSingleTouchStart$.pipe(
-      switchMap(() => concat(
-        this._thresholdDrag$.pipe(
-          pairwise(),
-          map(double => ({
-            deltaX : double[1].touches[0].screenX - double[0].touches[0].screenX,
-            deltaY : double[1].touches[0].screenY - double[0].touches[0].screenY,
-          })),
-          scan((acc, _curr) => acc),
-          map(v => v.deltaX ** 2 > v.deltaY ** 2),
-        ),
-        of(false),
-      )),
-      startWith(false),
-      distinctUntilChanged(),
-      shareReplay(1)
-    )
-
-    this.showInitiator$ = combineLatest(
-      this.showProperties$,
-      this.showDelta$,
-    ).pipe(
-      map(([flag1, flag2]) => !flag1 && !flag2),
-    )
-
-    this.showScreen$ = combineLatest(
-      merge(
-        fromEvent(this.initiator.nativeElement, 'touchstart'),
-        fromEvent(this.initiator.nativeElement, 'touchend'),
-      ),
-      this.showInitiator$,
-    ).pipe(
-      map(([ev, showInitiator]: [TouchEvent, boolean]) => showInitiator && ev.touches.length === 1),
-    )
-
-    this.showDelta$.pipe(
-      filter(flag => flag),
-      switchMapTo(this._thresholdDrag$.pipe(
-        pairwise(),
-        map(double => double[1].touches[0].screenX - double[0].touches[0].screenX)
-      )),
-      takeUntil(this._onDestroySubject)
-    ).subscribe(ev => {
-      this.deltaValue.emit({
-        delta: ev,
-        selectedProp: this.focusedProperty
-      })
-    })
-
-    const offsetObs$ = this.initiatorSingleTouchStart$.pipe(
-      switchMap(() => this._drag$)
-    )
-
-    combineLatest(
-      this.showProperties$,
-      offsetObs$,
-    ).pipe(
-      filter(v => v[0]),
-      map(v => v[1]),
-      scan((acc, curr) => {
-        const { startY } = acc
-        const { screenY } = curr.touches[0]
-        return {
-          startY: startY || screenY,
-          totalDeltaY: screenY - (startY || 0)
-        }
-      }, {
-        startY: null,
-        totalDeltaY: 0
-      }),
-      takeUntil(this._onDestroySubject),
-    ).subscribe(v => {
-      const deltaY = v.totalDeltaY
-      const cellHeight = this.menuContainer && this.tunableProperties && this.tunableProperties.length > 0 && this.menuContainer.nativeElement.offsetHeight / this.tunableProperties.length
-      const adjHeight = - this.focusedIndex * cellHeight - cellHeight * 0.5
-
-      const min = - cellHeight * 0.5
-      const max = - this.tunableProperties.length * cellHeight + cellHeight * 0.5
-      const finalYTranslate = clamp(adjHeight + deltaY, min, max )
-      this.menuTransform = `translate(0px, ${finalYTranslate}px)`
-    })
-
-    this.showProperties$.pipe(
-      takeUntil(this._onDestroySubject),
-      filter(v => !v),
-    ).subscribe(() => {
-      if (this.focusItemIndex >= 0) {
-        this._focusedProperties = this.tunableProperties[this.focusItemIndex]
-      }
-    })
-
-    this.showDelta$.pipe(
-      tap(flag => {
-        this.highlightedSubmenu$.next(this.focusedProperty.values[0])
-        if (!flag && !!this.subMenuIxObs) {
-          this.subMenuIxObs.disconnect()
-          this.subMenuIxObs = null
-        }
-      }),
-      filter(v => !!v),
-      // when options show again, options may have changed, so need to recalculate
-      tap(() => {
-        this.setValueContainerClampStart = null
-        this.setValueContainerWidth = null
-        this.setValueContainerClampEnd = null
-        this.setValueContainerOffset = null
-      }), 
-      switchMapTo(this._drag$.pipe(
-        scan((acc, curr) => {
-          const { startX } = acc
-          const { screenX } = curr.touches[0]
-          return {
-            startX: startX || screenX,
-            totalDeltaX: screenX - (startX  || 0)
-          }
-        }, {
-          startX: null,
-          totalDeltaX: 0
-        })
-      )),
-      takeUntil(this._onDestroySubject)
-    ).subscribe(({ totalDeltaX }) => {
-      if (!this.subMenuIxObs && this.subMenuIx) {
-        this.subMenuIxObs = new IntersectionObserver(ixs => {
-          const ix = ixs.find(({ intersectionRatio }) => intersectionRatio < 0.7)
-          if (!ix) return console.log(ixs)
-          const value = ix.target.getAttribute('data-submenu-value')
-          this.highlightedSubmenu$.next(value)
-        }, {
-          root: this.subMenuIx.nativeElement,
-          threshold: [ 0.1, 0.3, 0.5, 0.7, 0.9 ]
-        })
-
-        for (const btn of this.setValueContainer.nativeElement.children) {
-          this.subMenuIxObs.observe(btn)
-        }
-      }
-      if (!this.setValueContainerWidth) {
-        if (!this.setValueContainer) return
-        if (this.setValueContainer.nativeElement.children.length === 0) return
-        const { children, clientWidth } = this.setValueContainer.nativeElement
-
-        this.setValueContainerWidth = clientWidth
-        const firstChildWidth = children[0].clientWidth
-        const lastChildWidth = children[children.length - 1].clientWidth
-
-        this.setValueContainerOffset = firstChildWidth / -2
-        this.setValueContainerClampStart = firstChildWidth / -2
-        this.setValueContainerClampEnd = lastChildWidth / 2 - clientWidth
-      }
-      const actualDeltaX = clamp(totalDeltaX + this.setValueContainerOffset, this.setValueContainerClampStart, this.setValueContainerClampEnd)
-      this.subMenuTransform = `translate(${actualDeltaX}px , 0px)`
-    })
-
-    this.showDelta$.pipe(
-      takeUntil(this._onDestroySubject),
-      filter(v => !v)
-    ).subscribe(() => this.valueSelected.emit({ selectedProp: this.focusedProperty, value: this.highlightedSubmenu$.value }))
-  }
-
-  public highlightedSubmenu$: BehaviorSubject<string> = new BehaviorSubject(null)
-
-  private setValueContainerOffset = null
-  private setValueContainerClampEnd = null
-  private setValueContainerClampStart = null
-  private setValueContainerWidth = null
-  public subMenuTransform = `translate(0px, 0px)`
-  public menuTransform = `translate(0px, 0px)`
-
-  public focusItemIndex: number = 0
-
-}
diff --git a/src/ui/nehubaContainer/mobileOverlay/mobileOverlay.style.css b/src/ui/nehubaContainer/mobileOverlay/mobileOverlay.style.css
deleted file mode 100644
index 8d548523eaefd725bb5baa490dfc38e3e7abdc2e..0000000000000000000000000000000000000000
--- a/src/ui/nehubaContainer/mobileOverlay/mobileOverlay.style.css
+++ /dev/null
@@ -1,110 +0,0 @@
-:host
-{
-  width: 100%;
-  height: 100%;
-  top: 0;
-  left: 0;
-  position: absolute;
-  z-index: 9;
-
-  pointer-events: none;
-}
-
-:host [screen]
-{
-  width: 100%;
-  height: 100%;
-  top: 0;
-  left: 0;
-  position: absolute;
-  z-index: 99999;
-
-  color : black;
-  background-color: rgba(255, 255, 255, 0.5);
-
-  transition: all 200ms linear;
-}
-
-:host-context([darktheme="true"]) [screen]
-{
-  color : white;
-  background-color: rgba(0, 0, 0, 0.5);
-}
-
-[intersector]
-{
-  position: absolute;
-  top: 50%;
-  left: 0;
-  width: 100%;
-  height: 50%;
-
-  display: flex;
-  flex-direction: column;
-  justify-content: flex-start;
-  align-items: center;
-}
-
-[mobileMenuContainer]
-{
-  z-index: 1000;
-}
-
-.scrollFocus:after
-{
-  content: ' ';
-  position:absolute;
-  width:100%;
-  height:100%;
-  top: 0;
-  left: 0;
-  
-  background-color: rgba(0, 0, 128, 0.2);
-}
-
-:host-context([darktheme="true"]) .scrollFocus:after
-{
-  background-color: rgba(128, 128, 200, 0.2);
-}
-
-.base-container
-{
-  position: relative;
-  width: 100%;
-  left: 0;
-  top: 50%;
-  height: 0;
-  z-index: 9999;
-}
-
-div[delta]
-{
-  white-space: nowrap
-}
-
-.popup
-{
-  transition: all 120ms linear;
-  transform-origin: 50% 100%;
-}
-
-.scale-y-0
-{
-  transform: scale(0.5, 0);
-  opacity: 0;
-}
-
-.subMenu
-{
-  bottom: 15px;
-}
-
-.w-50
-{
-  width: 50%;
-}
-
-.sliver
-{
-  width: 1px;
-}
\ No newline at end of file
diff --git a/src/ui/nehubaContainer/mobileOverlay/mobileOverlay.template.html b/src/ui/nehubaContainer/mobileOverlay/mobileOverlay.template.html
deleted file mode 100644
index 791edddf1b9dda7ae39043f7746afa8703f87bef..0000000000000000000000000000000000000000
--- a/src/ui/nehubaContainer/mobileOverlay/mobileOverlay.template.html
+++ /dev/null
@@ -1,82 +0,0 @@
-<div screen [hidden]="!(showProperties$ | async)">
-  <div intersector #intersector>
-    <div [style.transform] = "menuTransform" class = "btn-group-vertical" role = "group" mobileMenuContainer #mobileMenuContainer>
-      <div 
-        *ngFor = "let p of tunableProperties; let i = index"
-        [ngClass] = "{'active' : p === focusedProperty, 'scrollFocus': i === focusItemIndex}" 
-        class = "btn btn-default theme-controlled property scrollFocus">
-        <!-- scrollFocus class -->
-        <span>
-          {{ p.displayName || p.name }}
-        </span>
-      </div>
-    </div>
-  </div>
-</div>
-
-<!-- container class -->
-<div class="d-flex flex-column-reverse flex-nowrap align-items-center base-container position-relative">
-
-  <!-- ctrl nub -->
-  <div class="h-0 d-inline-flex align-items-center" [hidden]="!(showInitiator$ | async)" #initiator>
-    <div (contextmenu)="$event.stopPropagation(); $event.preventDefault();"
-      [ngStyle]="ctrlBtnPosition"
-      class="pe-all"
-      initiator>
-      <button mat-mini-fab color="primary">
-        <i class="fas fa-globe"></i>
-      </button>
-    </div>
-  </div>
-
-  <!-- guide text -->
-  <mat-card [ngClass]="{ 'scale-y-0': !(showScreen$ | async)  }"
-    class="mb-4 popup muted position-absolute subMenu">
-    <mat-card-content>
-      <ng-container *ngTemplateOutlet="guideTmpl">
-      </ng-container>
-    </mat-card-content>
-  </mat-card>
-
-  <!-- mobile set value -->
-  <div *ngIf="showDelta$ | async" class="position-absolute h-0 w-100 d-flex flex-row justify-content-end align-items-end">
-
-    <!-- intersection observer -->
-    <div class="w-50 d-flex flex-row flex-nowrap" #subMenuObserver>
-    
-      <!-- value selection container -->
-      <div class="position-relative mb-4" [style.transform]="subMenuTransform" #setValueContainer>
-        <!-- value selections -->
-        <ng-container *ngFor="let value of focusedProperty.values">
-          <!-- selected button -->
-          <ng-template
-            [ngIf]="focusedProperty.selected === value"
-            [ngIfElse]="notSelectedTmpl">
-            <button
-              [attr.data-submenu-value]="value"
-              mat-flat-button
-              [ngClass]="{ 'muted': (highlightedSubmenu$ | async) !== value }"
-              color="primary"
-              class="mr-2">
-              {{ value }}
-            </button>
-          </ng-template>
-
-          <!-- not selected button -->
-          <ng-template #notSelectedTmpl>
-            <button
-              [attr.data-submenu-value]="value"
-              mat-flat-button
-              [ngClass]="{ 'muted': (highlightedSubmenu$ | async) !== value }"
-              color="default"
-              class="mr-2">
-              {{ value }}
-            </button>
-          </ng-template>
-
-        </ng-container>
-      </div>
-    </div>
-  </div>
-
-</div>
diff --git a/src/ui/nehubaContainer/reorderPanelIndex.pipe.ts b/src/ui/nehubaContainer/reorderPanelIndex.pipe.ts
deleted file mode 100644
index 3e76f4d0234a6942743f9eeff983eb065b938298..0000000000000000000000000000000000000000
--- a/src/ui/nehubaContainer/reorderPanelIndex.pipe.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import { Pipe, PipeTransform } from "@angular/core";
-
-@Pipe({
-  name: 'reorderPanelIndexPipe',
-})
-
-export class ReorderPanelIndexPipe implements PipeTransform {
-  public transform(panelOrder: string, uncorrectedIndex: number) {
-    return uncorrectedIndex === null
-      ? null
-      : panelOrder.indexOf(uncorrectedIndex.toString())
-  }
-}
diff --git a/src/ui/ui.module.ts b/src/ui/ui.module.ts
index 1d9c79d562f70331b06637468450d964b6d733b4..2e083c87bbc17a268a43c2aba3cf1dd90acc5018 100644
--- a/src/ui/ui.module.ts
+++ b/src/ui/ui.module.ts
@@ -6,10 +6,6 @@ import { ScrollingModule } from "@angular/cdk/scrolling"
 import { HttpClientModule } from "@angular/common/http";
 import { AngularMaterialModule } from 'src/sharedModules'
 import { UtilModule } from "src/util";
-import { DownloadDirective } from "../util/directives/download.directive";
-import { MobileOverlay } from "./nehubaContainer/mobileOverlay/mobileOverlay.component";
-import { HumanReadableFileSizePipe } from "src/util/pipes/humanReadableFileSize.pipe";
-import { ReorderPanelIndexPipe } from "./nehubaContainer/reorderPanelIndex.pipe";
 import { ShareModule } from "src/share";
 import { AuthModule } from "src/auth";
 import { ActionDialog } from "./actionDialog/actionDialog.component";
@@ -33,13 +29,7 @@ import { HANDLE_SCREENSHOT_PROMISE, TypeHandleScrnShotPromise } from "../screens
     AuthModule,
   ],
   declarations: [
-    MobileOverlay,
     ActionDialog,
-    /* pipes */
-    HumanReadableFileSizePipe,
-    ReorderPanelIndexPipe,
-    /* directive */
-    DownloadDirective,
   ],
   providers: [
     {
@@ -51,8 +41,10 @@ import { HANDLE_SCREENSHOT_PROMISE, TypeHandleScrnShotPromise } from "../screens
       provide: HANDLE_SCREENSHOT_PROMISE,
       useValue: ((param) => {
         const canvas: HTMLCanvasElement = document.querySelector('#neuroglancer-container canvas')
-        if (!canvas) return Promise.reject(`element '#neuroglancer-container canvas' not found`)
-        const _ = (window as any).viewer.display.draw()
+        if (!canvas) {
+          return Promise.reject(`element '#neuroglancer-container canvas' not found`)
+        }
+        (window as any).viewer.display.draw()
         if (!param) {
           return new Promise(rs => {
             canvas.toBlob(blob => {
@@ -99,9 +91,6 @@ import { HANDLE_SCREENSHOT_PROMISE, TypeHandleScrnShotPromise } from "../screens
     }
   ],
   exports: [
-    // NehubaContainer,
-    MobileOverlay,
-    // StatusCardComponent,
   ]
 })
 
diff --git a/src/util/directives/download.directive.ts b/src/util/directives/download.directive.ts
deleted file mode 100644
index c0851002d0977cd7e534bc0bbf0b99cd446a7921..0000000000000000000000000000000000000000
--- a/src/util/directives/download.directive.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-import { Directive, ElementRef, Renderer2 } from "@angular/core";
-
-@Directive({
-  selector : 'a[download]',
-})
-
-export class DownloadDirective {
-
-  public downloadIcon: HTMLElement
-
-  constructor(public el: ElementRef, public rd2: Renderer2) {
-    this.downloadIcon = rd2.createElement('i')
-    rd2.addClass(this.downloadIcon, 'fas')
-    rd2.addClass(this.downloadIcon, 'fa-download-alt')
-  }
-
-  public ngAfterViewInit() {
-    this.rd2.appendChild(this.el.nativeElement, this.downloadIcon)
-  }
-}
diff --git a/src/util/fn.ts b/src/util/fn.ts
index ff9b1c07fc1d93938e4f6e62a990aa34ce84422a..6457ccf78a80061da34734ae0c3b2e20b0ffe238 100644
--- a/src/util/fn.ts
+++ b/src/util/fn.ts
@@ -17,6 +17,9 @@ export function getDebug() {
   return (window as any).__DEBUG__
 }
 
+// eslint-disable-next-line  @typescript-eslint/no-empty-function
+export function noop(){}
+
 export async function getExportNehuba() {
   // eslint-disable-next-line no-constant-condition
   while (true) {
@@ -26,15 +29,6 @@ export async function getExportNehuba() {
   }
 }
 
-const recursiveFlatten = (region, {ngId}) => {
-  return [{
-    ngId,
-    ...region,
-  }].concat(
-    ...((region.children && region.children.map && region.children.map(c => recursiveFlatten(c, { ngId : region.ngId || ngId })) ) || []),
-  )
-}
-
 export function getUuid(){
   return crypto.getRandomValues(new Uint32Array(1))[0].toString(16)
 }
@@ -140,7 +134,7 @@ export const CachedFunction = (config?: TCacheFunctionArg) => {
   }
 }
 
-// A quick, non security hash function
+// A quick, non secure hash function
 export class QuickHash {
   private length = 6
   constructor(opts?: any){
@@ -423,7 +417,7 @@ export function bufferUntil<T>(opts: ISwitchMapWaitFor) {
 export function defaultdict<T>(fn: () => T): Record<string, T> {
   const obj = {}
   return new Proxy(obj, {
-    get(target, prop, rec) {
+    get(target, prop, _rec) {
       if (!(prop in target)){
         target[prop] = fn()
       }
diff --git a/src/util/interfaces.ts b/src/util/interfaces.ts
index 6c057cb1ebe6acb7381f58864a0511cb3c1dc061..b9ba0df799dcd95099fdc94e718d20342bbfe62e 100644
--- a/src/util/interfaces.ts
+++ b/src/util/interfaces.ts
@@ -3,7 +3,6 @@
  */
 
 import { InjectionToken } from "@angular/core"
-import { Observable } from "rxjs"
 
 export interface IHasId{
   ['@id']: string
diff --git a/src/util/pipes/humanReadableFileSize.pipe.spec.ts b/src/util/pipes/humanReadableFileSize.pipe.spec.ts
deleted file mode 100644
index 74ae1113992802d8994023e8724acb4ee30a97ca..0000000000000000000000000000000000000000
--- a/src/util/pipes/humanReadableFileSize.pipe.spec.ts
+++ /dev/null
@@ -1,42 +0,0 @@
-import {} from 'jasmine'
-import { HumanReadableFileSizePipe } from './humanReadableFileSize.pipe'
-
-describe('humanReadableFileSize.pipe.ts', () => {
-  describe('HumanReadableFileSizePipe', () => {
-    it('steps properly when nubmers ets large', () => {
-      const pipe = new HumanReadableFileSizePipe()
-      const num = 12
-
-      expect(pipe.transform(num, 0)).toBe(`12 byte(s)`)
-      expect(pipe.transform(num * 1e3, 0)).toBe(`12 KB`)
-      expect(pipe.transform(num * 1e6, 0)).toBe(`12 MB`)
-      expect(pipe.transform(num * 1e9, 0)).toBe(`12 GB`)
-      expect(pipe.transform(num * 1e12, 0)).toBe(`12 TB`)
-
-      expect(pipe.transform(num * 1e15, 0)).toBe(`12000 TB`)
-    })
-
-    it('pads the correct zeros', () => {
-      const pipe = new HumanReadableFileSizePipe()
-      const num = 3.14159
-
-      expect(pipe.transform(num, 0)).toBe(`3 byte(s)`)
-      expect(pipe.transform(num, 1)).toBe(`3.1 byte(s)`)
-      expect(pipe.transform(num, 2)).toBe(`3.14 byte(s)`)
-      expect(pipe.transform(num, 3)).toBe(`3.142 byte(s)`)
-      expect(pipe.transform(num, 4)).toBe(`3.1416 byte(s)`)
-      expect(pipe.transform(num, 5)).toBe(`3.14159 byte(s)`)
-      expect(pipe.transform(num, 6)).toBe(`3.141590 byte(s)`)
-      expect(pipe.transform(num, 7)).toBe(`3.1415900 byte(s)`)
-    })
-
-    it('parses string as well as number', () => {
-      // TODO finish tests
-    })
-
-    it('throws when a non number is passed to either argument', () => {
-      // TODO finish tests
-    })
-
-  })
-})
diff --git a/src/util/pipes/humanReadableFileSize.pipe.ts b/src/util/pipes/humanReadableFileSize.pipe.ts
deleted file mode 100644
index 1abb96e6bcb826dd64a4ebda3183a7e3b910df85..0000000000000000000000000000000000000000
--- a/src/util/pipes/humanReadableFileSize.pipe.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-import { Pipe, PipeTransform } from "@angular/core";
-
-export const steps = [
-  'byte(s)',
-  'KB',
-  'MB',
-  'GB',
-  'TB',
-]
-
-@Pipe({
-  name: 'humanReadableFileSizePipe',
-})
-
-export class HumanReadableFileSizePipe implements PipeTransform {
-  public transform(input: string | number, precision: number = 2) {
-    let _input = Number(input)
-    if (!_input) { throw new Error(`HumanReadableFileSizePipe needs a string or a number that can be parsed to number`) }
-    const _precision = Number(precision)
-    if (isNaN(_precision)) { throw new Error(`precision must be a number`) }
-    let counter = 0
-    while (_input > 1000 && counter < 4) {
-      _input = _input / 1000
-      counter += 1
-    }
-    return `${_input.toFixed(precision)} ${steps[counter]}`
-  }
-}
diff --git a/src/util/pullable.ts b/src/util/pullable.ts
index 24ae06f3b70e51ac84cef085807866dfea5a2ade..6a5d87e96701b3c9c41553ce66c0f611054c0afa 100644
--- a/src/util/pullable.ts
+++ b/src/util/pullable.ts
@@ -1,5 +1,5 @@
 import { DataSource } from "@angular/cdk/collections"
-import { BehaviorSubject, Observable, ReplaySubject, Subscription, combineLatest, concat, of, timer } from "rxjs"
+import { BehaviorSubject, Observable, ReplaySubject, Subscription, concat, of, timer } from "rxjs"
 import { finalize, map, scan, shareReplay, startWith, tap } from "rxjs/operators"
 import { cachedPromise } from "./fn"
 
diff --git a/src/util/side-panel/side-panel.component.spec.ts b/src/util/side-panel/side-panel.component.spec.ts
index 73a50a69a04470d96248180aafab1d09ced161fd..5a7f71a4d35e01422c590a717f306dae3780dc0d 100644
--- a/src/util/side-panel/side-panel.component.spec.ts
+++ b/src/util/side-panel/side-panel.component.spec.ts
@@ -1,6 +1,7 @@
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 
 import { SidePanelComponent } from './side-panel.component';
+import { MatCardModule } from '@angular/material/card';
 
 describe('SidePanelComponent', () => {
   let component: SidePanelComponent;
@@ -8,7 +9,12 @@ describe('SidePanelComponent', () => {
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      declarations: [ SidePanelComponent ]
+      imports: [
+        MatCardModule,
+      ],
+      declarations: [ 
+        SidePanelComponent,
+      ]
     })
     .compileComponents();
 
diff --git a/src/viewerModule/nehuba/base.service/base.service.ts b/src/viewerModule/nehuba/base.service/base.service.ts
index bb42ed31f608691ce4b91084927b9a44d0a8a558..a6bfe046ab51e81f2d84db4930e9747d22f0388d 100644
--- a/src/viewerModule/nehuba/base.service/base.service.ts
+++ b/src/viewerModule/nehuba/base.service/base.service.ts
@@ -44,7 +44,7 @@ export class BaseService {
             regionmap.set(r.name, r)
           }
           const returnVal: Record<string, Record<number, NgMapReturnType>> = {}
-          for (const [url, { layer, region }] of Object.entries(record)) {
+          for (const [ /* url */ , { layer, region }] of Object.entries(record)) {
             
             
             for (const { name, label } of region) {
diff --git a/src/viewerModule/nehuba/layerCtrl.service/layerCtrl.effects.ts b/src/viewerModule/nehuba/layerCtrl.service/layerCtrl.effects.ts
index 68f181a8654696b4c3c080bc8f079f694dce4591..b8e5e4b26a8f59e6f0dce71eaf8ee227d6e46e80 100644
--- a/src/viewerModule/nehuba/layerCtrl.service/layerCtrl.effects.ts
+++ b/src/viewerModule/nehuba/layerCtrl.service/layerCtrl.effects.ts
@@ -172,7 +172,7 @@ export class LayerCtrlEffects {
         parcNgLayers: from(this.sapi.getTranslatedLabelledNgMap(parcellation, template)).pipe(
           map(val => {
             const returnVal: Record<string, NgSegLayerSpec> = {}
-            for (const [ url, { layer, region } ] of Object.entries(val)) {
+            for (const [ /** url */, { layer, region } ] of Object.entries(val)) {
               const { name } = region[0]
               const ngId = getParcNgId(atlas, template, parcellation, {
                 id: '',
diff --git a/src/viewerModule/nehuba/layoutOverlay/nehuba.layoutOverlay/nehuba.layoutOverlay.component.ts b/src/viewerModule/nehuba/layoutOverlay/nehuba.layoutOverlay/nehuba.layoutOverlay.component.ts
index a6e58b8462cb398d87f2f6b26b61607110950f2d..118031cc0806bb692dead3bff0f7811adae32759 100644
--- a/src/viewerModule/nehuba/layoutOverlay/nehuba.layoutOverlay/nehuba.layoutOverlay.component.ts
+++ b/src/viewerModule/nehuba/layoutOverlay/nehuba.layoutOverlay/nehuba.layoutOverlay.component.ts
@@ -4,7 +4,7 @@ import { combineLatest, fromEvent, interval, merge, Observable, of, Subject, Sub
 import { userInterface } from "src/state";
 import { NehubaViewerUnit } from "../../nehubaViewer/nehubaViewer.component";
 import { NEHUBA_INSTANCE_INJTKN, takeOnePipe, getFourPanel, getHorizontalOneThree, getSinglePanel, getPipPanel, getVerticalOneThree } from "../../util";
-import { QUICKTOUR_DESC, ARIA_LABELS, IDS } from 'common/constants'
+import { QUICKTOUR_DESC, QUICKTOUR_DESC_MD, ARIA_LABELS, IDS } from 'common/constants'
 import { IQuickTourData } from "src/ui/quickTour/constrants";
 import { debounce, debounceTime, distinctUntilChanged, filter, map, mapTo, switchMap, take } from "rxjs/operators";
 import {panelOrder} from "src/state/userInterface/selectors";
@@ -28,6 +28,7 @@ export class NehubaLayoutOverlay implements OnDestroy{
   public quickTourSliceViewSlide: IQuickTourData = {
     order: 1,
     description: QUICKTOUR_DESC.SLICE_VIEW,
+    descriptionMd: QUICKTOUR_DESC_MD.SLICE_VIEW
   }
 
   public quickTour3dViewSlide: IQuickTourData = {
diff --git a/src/viewerModule/nehuba/layoutOverlay/nehuba.layoutOverlay/nehuba.layoutOverlay.template.html b/src/viewerModule/nehuba/layoutOverlay/nehuba.layoutOverlay/nehuba.layoutOverlay.template.html
index 5ae334a2db080f80a983734c1004c3e3e46e231b..18968039f924b3625f13254ff2b2d6e0bf346f61 100644
--- a/src/viewerModule/nehuba/layoutOverlay/nehuba.layoutOverlay/nehuba.layoutOverlay.template.html
+++ b/src/viewerModule/nehuba/layoutOverlay/nehuba.layoutOverlay/nehuba.layoutOverlay.template.html
@@ -7,6 +7,7 @@
     [iav-window-resize-time]="64"
     (iav-window-resize-event)="setQuickTourPos()"
     quick-tour
+    [quick-tour-description-md]="quickTourSliceViewSlide.descriptionMd"
     [quick-tour-description]="quickTourSliceViewSlide.description"
     [quick-tour-order]="quickTourSliceViewSlide.order"
     [quick-tour-overwrite-arrow]="sliceViewArrow"
diff --git a/src/viewerModule/nehuba/mesh.service/mesh.service.ts b/src/viewerModule/nehuba/mesh.service/mesh.service.ts
index d46e128f4a84d082272101b67a215bf75d5165c3..2af102701593d4918f8b4c45e3eef92f2382952b 100644
--- a/src/viewerModule/nehuba/mesh.service/mesh.service.ts
+++ b/src/viewerModule/nehuba/mesh.service/mesh.service.ts
@@ -39,7 +39,7 @@ export class NehubaMeshService implements OnDestroy {
       const ngIdRecord: Record<string, number[]> = {}
 
       for (const [ngId, labelToRegion] of Object.entries(record)) {
-        for (const [label, _region] of Object.entries(labelToRegion)) {
+        for (const [label, ] of Object.entries(labelToRegion)) {
           if (!ngIdRecord[ngId]) {
             ngIdRecord[ngId] = []
           }
diff --git a/src/viewerModule/nehuba/module.ts b/src/viewerModule/nehuba/module.ts
index 8243707dae27438a851e0ccd38cf39fa428519ff..682fae0bb9cf878ebd3ff18007a1ad26eb8cbfb0 100644
--- a/src/viewerModule/nehuba/module.ts
+++ b/src/viewerModule/nehuba/module.ts
@@ -1,4 +1,4 @@
-import { APP_INITIALIZER, CUSTOM_ELEMENTS_SCHEMA, NgModule } from "@angular/core";
+import { APP_INITIALIZER, NgModule } from "@angular/core";
 import { NehubaViewerContainerDirective } from './nehubaViewerInterface/nehubaViewerInterface.directive'
 import { IMPORT_NEHUBA_INJECT_TOKEN, NehubaViewerUnit } from "./nehubaViewer/nehubaViewer.component";
 import { CommonModule } from "@angular/common";
diff --git a/src/viewerModule/nehuba/navigation.service/navigation.base.service.ts b/src/viewerModule/nehuba/navigation.service/navigation.base.service.ts
index dd82454761ad41d4ccb18f8a37ea3abbabe3c6f5..66413f1ffe994dab36f2ecc0aa3eab5c6225b374 100644
--- a/src/viewerModule/nehuba/navigation.service/navigation.base.service.ts
+++ b/src/viewerModule/nehuba/navigation.service/navigation.base.service.ts
@@ -1,6 +1,6 @@
 import { Inject, Injectable, Optional } from "@angular/core";
 import { concat, EMPTY, NEVER, Observable, of } from "rxjs";
-import { delay, exhaustMap, shareReplay, switchMap, take, tap } from "rxjs/operators";
+import { delay, exhaustMap, shareReplay, switchMap, take } from "rxjs/operators";
 import { TNehubaViewerUnit } from "../constants";
 import { NEHUBA_INSTANCE_INJTKN } from "../util";
 
diff --git a/src/viewerModule/nehuba/nehubaViewer/nehubaViewer.component.ts b/src/viewerModule/nehuba/nehubaViewer/nehubaViewer.component.ts
index e1806ae87856ee7dd6756f15e122ce54e3bc1409..e0e25cd158aedca533bbe1b9a336832ff2f82298 100644
--- a/src/viewerModule/nehuba/nehubaViewer/nehubaViewer.component.ts
+++ b/src/viewerModule/nehuba/nehubaViewer/nehubaViewer.component.ts
@@ -13,17 +13,6 @@ import { IColorMap, SET_COLORMAP_OBS, SET_LAYER_VISIBILITY } from "../layerCtrl.
  */
 import { INgLayerCtrl, NG_LAYER_CONTROL, SET_SEGMENT_VISIBILITY, TNgLayerCtrl } from "../layerCtrl.service/layerCtrl.util";
 
-const NG_LANDMARK_LAYER_NAME = 'spatial landmark layer'
-const NG_USER_LANDMARK_LAYER_NAME = 'user landmark layer'
-
-/**
- * optimized for nehubaConfig.layout.useNehubaPerspective.fixedZoomPerspectiveSlices
- *  sliceZoom
- *  sliceViewportWidth
- *  sliceViewportHeight
- */
-const NG_LANDMARK_CONSTANT = 1e-8
-
 export const IMPORT_NEHUBA_INJECT_TOKEN = `IMPORT_NEHUBA_INJECT_TOKEN`
 
 interface LayerLabelIndex {
@@ -85,8 +74,7 @@ export class NehubaViewerUnit implements OnDestroy {
         url?: string
       }
     }> = new EventEmitter()
-  @Output() public mouseoverLandmarkEmitter: EventEmitter<string> = new EventEmitter()
-  @Output() public mouseoverUserlandmarkEmitter: EventEmitter<string> = new EventEmitter()
+
   @Output() public regionSelectionEmitter: EventEmitter<{
     segment: number
     layer: {
@@ -95,6 +83,7 @@ export class NehubaViewerUnit implements OnDestroy {
   }}> = new EventEmitter()
   @Output() public errorEmitter: EventEmitter<any> = new EventEmitter()
 
+  @Output() public totalMeshesToLoad = new EventEmitter<number>()
 
   /* only used to set initial navigation state */
   public initNav: any
@@ -319,7 +308,7 @@ export class NehubaViewerUnit implements OnDestroy {
             totalMeshes += labelIndicies.length
             this.nehubaViewer.setMeshesToLoad(labelIndicies, layer)
           }
-          // TODO implement total mesh to be loaded and mesh loading UI
+          this.totalMeshesToLoad.emit(totalMeshes)
         }),
       )
     } else {
@@ -336,25 +325,6 @@ export class NehubaViewerUnit implements OnDestroy {
     }
   }
 
-  public spatialLandmarkSelectionChanged(labels: number[]) {
-    const getCondition = (label: number) => `if(label > ${label - 0.1} && label < ${label + 0.1} ){${FRAGMENT_EMIT_RED}}`
-    const newShader = `void main(){ ${labels.map(getCondition).join('else ')}else {${FRAGMENT_EMIT_WHITE}} }`
-    if (!this.nehubaViewer) {
-      this.log.warn('setting special landmark selection changed failed ... nehubaViewer is not yet defined')
-      return
-    }
-    const landmarkLayer = this.nehubaViewer.ngviewer.layerManager.getLayerByName(NG_LANDMARK_LAYER_NAME)
-    if (!landmarkLayer) {
-      this.log.warn('landmark layer could not be found ... will not update colour map')
-      return
-    }
-    if (labels.length === 0) {
-      landmarkLayer.layer.displayState.fragmentMain.restoreState(FRAGMENT_MAIN_WHITE)
-    } else {
-      landmarkLayer.layer.displayState.fragmentMain.restoreState(newShader)
-    }
-  }
-
   public navPosReal: [number, number, number] = [0, 0, 0]
   public navPosVoxel: [number, number, number] = [0, 0, 0]
 
@@ -483,20 +453,6 @@ export class NehubaViewerUnit implements OnDestroy {
     )
   }
 
-  private userLandmarkShader: string = FRAGMENT_MAIN_WHITE
-
-  public removeSpatialSearch3DLandmarks() {
-    this.removeLayer({
-      name : NG_LANDMARK_LAYER_NAME,
-    })
-  }
-
-  public removeuserLandmarks() {
-    this.removeLayer({
-      name : NG_USER_LANDMARK_LAYER_NAME,
-    })
-  }
-
   public setLayerVisibility(condition: {name: string|RegExp}, visible: boolean) {
     if (!this.nehubaViewer) {
       return false
@@ -798,19 +754,6 @@ export class NehubaViewerUnit implements OnDestroy {
         })
       })
 
-    // TODO bug: mouseoverlandmarkemitter does not emit empty for VTK layer when user mouse click
-    this.ondestroySubscriptions.push(
-      this.nehubaViewer.mouseOver.layer
-        .filter(obj => obj.layer.name === NG_LANDMARK_LAYER_NAME)
-        .subscribe(obj => this.mouseoverLandmarkEmitter.emit(obj.value)),
-    )
-
-    this.ondestroySubscriptions.push(
-      this.nehubaViewer.mouseOver.layer
-        .filter(obj => obj.layer.name === NG_USER_LANDMARK_LAYER_NAME)
-        .subscribe(obj => this.mouseoverUserlandmarkEmitter.emit(obj.value)),
-    )
-
     this._s4$ = this.nehubaViewer.navigationState.position.inRealSpace
       .filter(v => typeof v !== 'undefined' && v !== null)
       .subscribe(v => {
diff --git a/src/viewerModule/nehuba/nehubaViewerGlue/nehubaViewerGlue.component.ts b/src/viewerModule/nehuba/nehubaViewerGlue/nehubaViewerGlue.component.ts
index 1ff596295312d22d8d87e775c3c12821f0f1cbcb..c3bc899bd568f5242f37f4a90f2cf1f57f78579b 100644
--- a/src/viewerModule/nehuba/nehubaViewerGlue/nehubaViewerGlue.component.ts
+++ b/src/viewerModule/nehuba/nehubaViewerGlue/nehubaViewerGlue.component.ts
@@ -1,4 +1,4 @@
-import { ChangeDetectionStrategy, Component, EventEmitter, Inject, OnDestroy, Optional, Output, TemplateRef, ViewChild } from "@angular/core";
+import { ChangeDetectionStrategy, Component, EventEmitter, Inject, OnDestroy, Optional, Output } from "@angular/core";
 import { select, Store } from "@ngrx/store";
 import { ClickInterceptor, CLICK_INTERCEPTOR_INJECTOR } from "src/util";
 import { distinctUntilChanged } from "rxjs/operators";
diff --git a/src/viewerModule/nehuba/nehubaViewerInterface/nehubaViewerInterface.directive.spec.ts b/src/viewerModule/nehuba/nehubaViewerInterface/nehubaViewerInterface.directive.spec.ts
index 19314d6737ebfd0c3229b41f3fb62055d9b0bcb6..db6f3a030a26adaaf5748a2a0e1b4816f0080c85 100644
--- a/src/viewerModule/nehuba/nehubaViewerInterface/nehubaViewerInterface.directive.spec.ts
+++ b/src/viewerModule/nehuba/nehubaViewerInterface/nehubaViewerInterface.directive.spec.ts
@@ -94,8 +94,6 @@ describe('> nehubaViewerInterface.directive.ts', () => {
         layersChanged: new Subject(),
         nehubaReady: new Subject(),
         mouseoverSegmentEmitter: new Subject(),
-        mouseoverLandmarkEmitter: new Subject(),
-        mouseoverUserlandmarkEmitter: new Subject(),
         elementRef: {
           nativeElement: {}
         },
@@ -171,76 +169,7 @@ describe('> nehubaViewerInterface.directive.ts', () => {
     })
   
     describe('> subscription of nehuba instance', () => {
-      describe('> mouseoverUserlandmarkEmitter', () => {
-        let spyNehubaViewerInstance: any
-        let dispatchSpy: jasmine.Spy
-        let directiveInstance: NehubaViewerContainerDirective
-        const template = {}
-        const lifecycle = {}
-        beforeEach(() => {
-
-          spyNehubaViewerInstance = {
-            config: null,
-            lifecycle: null,
-            templateId: null,
-            errorEmitter: new Subject(),
-            viewerPositionChange: new Subject(),
-            layersChanged: new Subject(),
-            nehubaReady: new Subject(),
-            mouseoverSegmentEmitter: new Subject(),
-            mouseoverLandmarkEmitter: new Subject(),
-            mouseoverUserlandmarkEmitter: new Subject(),
-            elementRef: {
-              nativeElement: {}
-            }
-          }
-          const mockStore = TestBed.inject(MockStore)
-          dispatchSpy = spyOn(mockStore, 'dispatch')
-
-          const fixture = TestBed.createComponent(DummyCmp)
-          const directive = fixture.debugElement.query(
-            By.directive(NehubaViewerContainerDirective)
-          )
-          
-          const spyComRef = {
-            destroy: jasmine.createSpy('destroy')
-          }
-          directiveInstance = directive.injector.get(NehubaViewerContainerDirective)
-          spyOnProperty(directiveInstance, 'nehubaViewerInstance').and.returnValue(spyNehubaViewerInstance)
-          spyOn(directiveInstance['el'], 'clear').and.callFake(() => {})
-          spyOn(directiveInstance, 'clear').and.callFake(() => {})
-          // casting return value to any is not perfect, but since only 2 methods and 1 property is used, it's a quick way 
-          // rather than allow component to be created
-          spyOn(directiveInstance['el'], 'createComponent').and.returnValue(spyComRef as any)
-
-        })
-
-        afterEach(() => {
-          dispatchSpy.calls.reset()
-        })
-        it('> single null emits null', fakeAsync(() => {
-
-        }))
 
-        it('> single value emits value', fakeAsync(() => {
-
-        }))
-
-        describe('> double value in 140ms emits last value', () => {
-
-          it('> null - 24 emits 24', fakeAsync(() => {
-
-          }))
-          it('> 24 - null emits null', fakeAsync(() => {
-
-
-          }))
-        })
-      
-        it('> single value outside 140 ms emits separately', fakeAsync(() => {
-
-        }))
-      })
     })
   })
 })
diff --git a/src/viewerModule/nehuba/nehubaViewerInterface/nehubaViewerInterface.directive.ts b/src/viewerModule/nehuba/nehubaViewerInterface/nehubaViewerInterface.directive.ts
index aee39e6f48641ebdb9b5b8051f23c6c023a91545..45d9228cb40e036d94b3d78c644c722cf043e600 100644
--- a/src/viewerModule/nehuba/nehubaViewerInterface/nehubaViewerInterface.directive.ts
+++ b/src/viewerModule/nehuba/nehubaViewerInterface/nehubaViewerInterface.directive.ts
@@ -1,8 +1,8 @@
-import { Directive, ViewContainerRef, ComponentRef, OnDestroy, Output, EventEmitter, Optional, ChangeDetectorRef, ComponentFactoryResolver, ComponentFactory } from "@angular/core";
+import { Directive, ViewContainerRef, ComponentRef, OnDestroy, Output, EventEmitter, Optional, ChangeDetectorRef } from "@angular/core";
 import { NehubaViewerUnit } from "../nehubaViewer/nehubaViewer.component";
 import { Store, select } from "@ngrx/store";
-import { Subscription, Observable, asyncScheduler, combineLatest } from "rxjs";
-import { distinctUntilChanged, filter, debounceTime, scan, map, throttleTime, switchMap, take, tap } from "rxjs/operators";
+import { Subscription, Observable, combineLatest } from "rxjs";
+import { distinctUntilChanged, filter, debounceTime, scan, map, switchMap, take } from "rxjs/operators";
 import { serializeSegment } from "../util";
 import { LoggingService } from "src/logging";
 import { arrayOfPrimitiveEqual } from 'src/util/fn'
@@ -313,19 +313,6 @@ export class NehubaViewerContainerDirective implements OnDestroy{
         map((map: Map<string, any>) => Array.from(map.entries()).filter(([_ngId, { segmentId }]) => segmentId)),
       ).subscribe(val => this.handleMouseoverSegments(val)),
 
-      this.nehubaViewerInstance.mouseoverLandmarkEmitter.pipe(
-        distinctUntilChanged()
-      ).subscribe(label => {
-        console.warn(`mouseover landmark`, label)
-      }),
-
-      this.nehubaViewerInstance.mouseoverUserlandmarkEmitter.pipe(
-        throttleTime(160, asyncScheduler, {trailing: true}),
-      ).subscribe(label => {
-        const idx = Number(label.replace('label=', ''))
-        // TODO 
-        // this is exclusive for vtk layer
-      }),
 
       combineLatest([
         this.nehubaViewerInstance.mousePosInVoxel$,
diff --git a/src/viewerModule/nehuba/util.ts b/src/viewerModule/nehuba/util.ts
index 81aed3560abe6fe1f41b9faf13211d1002702591..c8d56c7e5ba037ab8366e4ca40d0066481146789 100644
--- a/src/viewerModule/nehuba/util.ts
+++ b/src/viewerModule/nehuba/util.ts
@@ -1,7 +1,7 @@
 import { InjectionToken } from '@angular/core'
 import { Observable, pipe } from 'rxjs'
 import { filter, scan, take } from 'rxjs/operators'
-import { getExportNehuba, getViewer } from 'src/util/fn'
+import { getViewer } from 'src/util/fn'
 import { NehubaViewerUnit } from './nehubaViewer/nehubaViewer.component'
 import { userInterface } from 'src/state'
 
diff --git a/src/viewerModule/nehuba/viewerCtrl/effects.ts b/src/viewerModule/nehuba/viewerCtrl/effects.ts
index fd10b9db4dabeadb61bd8f75683b3492081d7a74..5eeaafed8eaf61c7d03a5ddee0cb55759b39a8e6 100644
--- a/src/viewerModule/nehuba/viewerCtrl/effects.ts
+++ b/src/viewerModule/nehuba/viewerCtrl/effects.ts
@@ -2,7 +2,7 @@ import { Injectable } from "@angular/core";
 import { createEffect } from "@ngrx/effects";
 import { Store } from "@ngrx/store";
 import { of } from "rxjs";
-import { mapTo, switchMap } from "rxjs/operators";
+import { switchMap } from "rxjs/operators";
 import { atlasSelection, userInterface } from "src/state";
 
 @Injectable()
diff --git a/src/viewerModule/nehuba/viewerCtrl/perspectiveViewSlider/perspectiveViewSlider.component.ts b/src/viewerModule/nehuba/viewerCtrl/perspectiveViewSlider/perspectiveViewSlider.component.ts
index 67706f44a39f0b2600e75574dcfe8e25f41a18ac..6342411ebf03fabb2d1c816eac98cf15695a8451 100644
--- a/src/viewerModule/nehuba/viewerCtrl/perspectiveViewSlider/perspectiveViewSlider.component.ts
+++ b/src/viewerModule/nehuba/viewerCtrl/perspectiveViewSlider/perspectiveViewSlider.component.ts
@@ -1,7 +1,7 @@
 import { Component, OnDestroy, Inject, ViewChild, ChangeDetectionStrategy } from "@angular/core";
 import { FormControl } from "@angular/forms";
 import { select, Store } from "@ngrx/store";
-import { combineLatest, concat, forkJoin, NEVER, Observable, of, Subject, Subscription, throwError } from "rxjs";
+import { combineLatest, concat, NEVER, Observable, of, Subject, Subscription } from "rxjs";
 import { switchMap, distinctUntilChanged, map, debounceTime, shareReplay, take, withLatestFrom } from "rxjs/operators";
 import { SAPI } from "src/atlasComponents/sapi";
 import { SxplrTemplate } from "src/atlasComponents/sapi/sxplrTypes"
@@ -292,7 +292,7 @@ export class PerspectiveViewSlider implements OnDestroy {
         this.currentTemplateSize$,
         this.rangeControlIsVertical$,
       ]).pipe(
-        map(([ navigation, viewportSize, ctrl, templateSize, isVertical ]) => {
+        map(([ navigation, viewportSize, ctrl, templateSize, ..._rest ]) => {
           if (!ctrl || !(templateSize?.real) || !navigation) return null
 
           const { zoom, position } = navigation
diff --git a/src/viewerModule/threeSurfer/store/effects.ts b/src/viewerModule/threeSurfer/store/effects.ts
index 501107552338fc19658b5757c13610b3fae15782..86992a1c3330ed1b3150467d04aa4f984cde169e 100644
--- a/src/viewerModule/threeSurfer/store/effects.ts
+++ b/src/viewerModule/threeSurfer/store/effects.ts
@@ -1,7 +1,7 @@
 import { Injectable } from "@angular/core";
 import { createEffect } from "@ngrx/effects";
 import { select, Store } from "@ngrx/store";
-import { EMPTY, forkJoin, merge, Observable, of, pipe, throwError } from "rxjs";
+import { EMPTY, forkJoin, merge, Observable, of, pipe } from "rxjs";
 import { debounceTime, map, switchMap, withLatestFrom, filter, shareReplay, distinctUntilChanged } from "rxjs/operators";
 import { SAPI } from "src/atlasComponents/sapi";
 import { SxplrAtlas, SxplrParcellation, SxplrTemplate } from "src/atlasComponents/sapi/sxplrTypes"
@@ -118,7 +118,7 @@ export class ThreeSurferEffects {
   ))
 
   onATPDebounceAddBaseLayers$ = createEffect(() => this.onATPDebounceThreeSurferLayers$.pipe(
-    switchMap(({ labels, surfaces }) => {
+    switchMap(({ labels }) => {
       const labelMaps: ThreeSurferCustomLabelLayer[] = []
       for (const key in labels) {
         const { laterality, url } = labels[key]
diff --git a/src/viewerModule/threeSurfer/threeSurferGlue/threeSurfer.component.ts b/src/viewerModule/threeSurfer/threeSurferGlue/threeSurfer.component.ts
index e4e729b1cfcf6817d00afd57681e2bbc9c817e9c..60ba8899d52403374120fdcd20c5460a3afd1734 100644
--- a/src/viewerModule/threeSurfer/threeSurferGlue/threeSurfer.component.ts
+++ b/src/viewerModule/threeSurfer/threeSurferGlue/threeSurfer.component.ts
@@ -613,7 +613,7 @@ export class ThreeSurferGlueCmp implements IViewer<'threeSurfer'>, AfterViewInit
         this.tsRef.applyColorMap(mesh, vertexIndices, {
           custom: actualApplyMap
         })
-        return
+        continue
       }
 
       const highlightIdx = new Set<number>()
diff --git a/src/viewerModule/viewerCmp/viewerCmp.component.ts b/src/viewerModule/viewerCmp/viewerCmp.component.ts
index 2dbd534dbd0a309ec23fcf1f6545a88bfe1b5a18..b0d53ca1162ec2a39f94a90a091c32dbd5ea3663 100644
--- a/src/viewerModule/viewerCmp/viewerCmp.component.ts
+++ b/src/viewerModule/viewerCmp/viewerCmp.component.ts
@@ -1,4 +1,4 @@
-import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, TemplateRef, ViewChild, ViewContainerRef } from "@angular/core";
+import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, TemplateRef, ViewChild } from "@angular/core";
 import { select, Store } from "@ngrx/store";
 import { combineLatest, Observable, Subscription } from "rxjs";
 import { debounceTime, map, shareReplay } from "rxjs/operators";
@@ -444,8 +444,8 @@ export class ViewerCmp implements OnDestroy {
   voiFeatureEntryCmp: EntryComponent
 
   async pullAllVoi(){
+    await wait(320)
     if (this.voiFeatureEntryCmp){
-      await wait(320)
       this.voiFeatureEntryCmp.pullAll()
     }
   }
diff --git a/src/widget/service.ts b/src/widget/service.ts
index 9430269418731ceb3b57810b54b26ef155ef7ef0..67856fb1f1c79ed1de0145394e3148f99c7bb633 100644
--- a/src/widget/service.ts
+++ b/src/widget/service.ts
@@ -1,5 +1,5 @@
 import { ComponentPortal } from "@angular/cdk/portal";
-import { ComponentFactory, ComponentFactoryResolver, ComponentRef, Injectable, Injector, ViewContainerRef } from "@angular/core";
+import { ComponentRef, Injectable, Injector, ViewContainerRef } from "@angular/core";
 import { RM_WIDGET } from "./constants";
 import { WidgetPortal } from "./widgetPortal/widgetPortal.component";
 
@@ -12,11 +12,6 @@ export class WidgetService {
   public vcr: ViewContainerRef
 
   private viewRefMap = new Map<WidgetPortal<unknown>, ComponentRef<WidgetPortal<unknown>>>()
-  private cf: ComponentFactory<WidgetPortal<unknown>>
-  
-  constructor(cfr: ComponentFactoryResolver){
-    this.cf = cfr.resolveComponentFactory(WidgetPortal)
-  }
 
   public addNewWidget<T>(Component: new (...arg: any) => T, injector: Injector): WidgetPortal<T> {
     const inj = Injector.create({
@@ -26,7 +21,8 @@ export class WidgetService {
       }],
       parent: injector
     })
-    const widgetPortal = this.vcr.createComponent(this.cf, 0, inj) as ComponentRef<WidgetPortal<T>>
+    
+    const widgetPortal = this.vcr.createComponent(WidgetPortal, {index: 0, injector: inj}) as ComponentRef<WidgetPortal<T>>
     const cmpPortal = new ComponentPortal<T>(Component, this.vcr, inj)
     
     this.viewRefMap.set(widgetPortal.instance, widgetPortal)