diff --git a/deploy/datasets/index.js b/deploy/datasets/index.js
index abb1ef174225f58b62f5e9afdb3c9696589a5f05..e974366263cff811887167510658d9a63938f652 100644
--- a/deploy/datasets/index.js
+++ b/deploy/datasets/index.js
@@ -2,7 +2,7 @@ const express = require('express')
 const path = require('path')
 const fs = require('fs')
 const datasetsRouter = express.Router()
-const { init, getDatasets, getPreview } = require('./query')
+const { init, getDatasets, getPreview, getDatasetFromId, getDatasetFileAsZip } = require('./query')
 const url = require('url')
 const qs = require('querystring')
 
@@ -10,21 +10,24 @@ const bodyParser = require('body-parser')
 datasetsRouter.use(bodyParser.urlencoded({ extended: false }))
 datasetsRouter.use(bodyParser.json())
 
-
 init().catch(e => {
   console.warn(`dataset init failed`, e)
 })
 
-datasetsRouter.use((req, res, next) => {
-  res.setHeader('Cache-Control', 'no-cache')
+const cacheMaxAge24Hr = (_req, res, next) => {
+  const oneDay = 24 * 60 * 60
+  res.setHeader('Cache-Control', `max-age=${oneDay}`)
   next()
-})
-
+}
 
+const noCacheMiddleWare = (_req, res, next) => {
+  res.setHeader('Cache-Control', 'no-cache')
+  next()
+}
 
-datasetsRouter.use('/spatialSearch', require('./spatialRouter'))
+datasetsRouter.use('/spatialSearch', noCacheMiddleWare, require('./spatialRouter'))
 
-datasetsRouter.get('/templateName/:templateName', (req, res, next) => {
+datasetsRouter.get('/templateName/:templateName', noCacheMiddleWare, (req, res, next) => {
   const { templateName } = req.params
   const { user } = req
   getDatasets({ templateName, user })
@@ -40,7 +43,7 @@ datasetsRouter.get('/templateName/:templateName', (req, res, next) => {
     })
 })
 
-datasetsRouter.get('/parcellationName/:parcellationName', (req, res, next) => {
+datasetsRouter.get('/parcellationName/:parcellationName', noCacheMiddleWare, (req, res, next) => {
   const { parcellationName } = req.params
   const { user } = req
   getDatasets({ parcellationName, user })
@@ -56,7 +59,7 @@ datasetsRouter.get('/parcellationName/:parcellationName', (req, res, next) => {
     })
 })
 
-datasetsRouter.get('/preview/:datasetName', (req, res, next) => {
+datasetsRouter.get('/preview/:datasetName', cacheMaxAge24Hr, (req, res, next) => {
   const { datasetName } = req.params
   const ref = url.parse(req.headers.referer)
   const { templateSelected, parcellationSelected } = qs.parse(ref.query)
@@ -97,7 +100,7 @@ fs.readdir(RECEPTOR_PATH, (err, files) => {
   files.forEach(file => previewFileMap.set(`res/image/receptor/${file}`, path.join(RECEPTOR_PATH, file)))
 })
 
-datasetsRouter.get('/previewFile', (req, res) => {
+datasetsRouter.get('/previewFile', cacheMaxAge24Hr, (req, res) => {
   const { file } = req.query
   const filePath = previewFileMap.get(file)
   if (filePath) {
@@ -107,7 +110,37 @@ datasetsRouter.get('/previewFile', (req, res) => {
   }
 })
 
+const checkKgQuery = (req, res, next) => {
+  const { kgSchema } = req.query
+  if (kgSchema !== 'minds/core/dataset/v1.0.0') return res.status(400).send('Only kgSchema is required and the only accepted value is minds/core/dataset/v1.0.0')
+  else return next()
+}
 
+datasetsRouter.get('/kgInfo', checkKgQuery, cacheMaxAge24Hr, async (req, res) => {
+  
+  const { kgId } = req.query
+  const { user } = req
+  const stream = await getDatasetFromId({ user, kgId, returnAsStream: true })
+  stream.pipe(res)
+})
+
+datasetsRouter.get('/downloadKgFiles', checkKgQuery, cacheMaxAge24Hr, async (req, res) => {
+  const { kgId } = req.query
+  const { user } = req
+  try {
+    const stream = await getDatasetFileAsZip({ user, kgId })
+    res.setHeader('Content-Type', 'application/zip')
+    stream.pipe(res)
+  } catch (e) {
+    console.log('datasets/index#downloadKgFiles', e)
+    res.status(400).send(e)
+  }
+})
+
+/**
+ * TODO
+ * deprecate jszip in favour of archiver
+ */
 
 var JSZip = require("jszip");
 
@@ -140,14 +173,8 @@ datasetsRouter.post("/downloadParcellationThemself", (req,res, next) => {
     })
   }
 
-  zip.generateAsync({type:"base64"})
-      .then(function (content) {
-        // location.href="data:application/zip;base64,"+content;
-        res.end(content)
-      });
-
-
-
+  res.setHeader('Content-Type', 'application/zip')
+  zip.generateNodeStream().pipe(res)
 });
 
 module.exports = datasetsRouter
\ No newline at end of file
diff --git a/deploy/datasets/nii/jubrain-max-pmap-v22c_space-mnicolin27.nii b/deploy/datasets/nii/jubrain-max-pmap-v22c_space-mnicolin27.nii
deleted file mode 100644
index 502dcb1e31b901ea3191c86717795d91880b9e3e..0000000000000000000000000000000000000000
Binary files a/deploy/datasets/nii/jubrain-max-pmap-v22c_space-mnicolin27.nii and /dev/null differ
diff --git a/deploy/datasets/query.js b/deploy/datasets/query.js
index b0df2342c06065aeca75310e84db48a22571ebe3..19a4cdac963ee83c1c09c5476f0c6682e599da26 100644
--- a/deploy/datasets/query.js
+++ b/deploy/datasets/query.js
@@ -1,6 +1,8 @@
 const fs = require('fs')
 const request = require('request')
+const URL = require('url')
 const path = require('path')
+const archiver = require('archiver')
 const { commonSenseDsFilter } = require('./supplements/commonSense')
 const { getPreviewFile, hasPreview } = require('./supplements/previewFile')
 const { manualFilter: manualFilterDWM, manualMap: manualMapDWM } = require('./supplements/util/mapDwm')
@@ -9,7 +11,25 @@ const kgQueryUtil = require('./../auth/util')
 
 let cachedData = null
 let otherQueryResult = null
-const queryUrl = process.env.KG_DATASET_QUERY_URL || `https://kg.humanbrainproject.org/query/minds/core/dataset/v1.0.0/interactiveViewerKgQuery/instances?size=450&vocab=https%3A%2F%2Fschema.hbp.eu%2FmyQuery%2F`
+
+const KG_ROOT = process.env.KG_ROOT || `https://kg.humanbrainproject.org`
+const KG_PATH = process.env.KG_PATH || `/query/minds/core/dataset/v1.0.0/interactiveViewerKgQuery-v0_1`
+const KG_PARAM = {
+  size: process.env.KG_SEARCH_SIZE || '450',
+  vocab: process.env.KG_SEARCH_VOCAB || 'https://schema.hbp.eu/myQuery/'
+}
+
+const KG_QUERY_DATASETS_URL = new URL.URL(`${KG_ROOT}${KG_PATH}/instances`)
+for (let key in KG_PARAM) {
+  KG_QUERY_DATASETS_URL.searchParams.set(key, KG_PARAM[key])
+}
+
+const getKgQuerySingleDatasetUrl = ({ kgId }) => {
+  const _newUrl = new URL.URL(KG_QUERY_DATASETS_URL)
+  _newUrl.pathname = `${KG_PATH}/instances/${kgId}`
+  return _newUrl
+}
+
 const timeout = process.env.TIMEOUT || 5000
 const STORAGE_PATH = process.env.STORAGE_PATH || path.join(__dirname, 'data')
 
@@ -17,10 +37,10 @@ let getPublicAccessToken
 
 const fetchDatasetFromKg = async ({ user } = {}) => {
 
-  const { releasedOnly, option } = await getUserKGRequestInfo({ user })
+  const { releasedOnly, option } = await getUserKGRequestParam({ user })
 
   return await new Promise((resolve, reject) => {
-    request(`${queryUrl}${releasedOnly ? '&databaseScope=RELEASED' : ''}`, option, (err, resp, body) => {
+    request(`${KG_QUERY_DATASETS_URL}${releasedOnly ? '&databaseScope=RELEASED' : ''}`, option, (err, resp, body) => {
       if (err)
         return reject(err)
       if (resp.statusCode >= 400)
@@ -238,7 +258,7 @@ function filterByqueryArg(cubeDots) {
 
 async function getSpatialSearchOk({ user, boundingBoxInWaxhomV2VoxelSpace }) {
 
-    const { releasedOnly, option } = await getUserKGRequestInfo({ user })
+    const { releasedOnly, option } = await getUserKGRequestParam({ user })
 
     const spatialQuery = 'https://kg.humanbrainproject.org/query/minds/core/dataset/v1.0.0/spatialSimple/instances?size=10'
 
@@ -254,22 +274,30 @@ async function getSpatialSearchOk({ user, boundingBoxInWaxhomV2VoxelSpace }) {
     })
 }
 
-async function getUserKGRequestInfo({ user }) {
-    const accessToken = user && user.tokenset && user.tokenset.access_token
+let publicAccessToken
+
+async function getUserKGRequestParam({ user }) {
+    /**
+     * n.b. ACCESS_TOKEN env var is usually only set during dev
+     */
+    const accessToken = (user && user.tokenset && user.tokenset.access_token) || process.env.ACCESS_TOKEN
     const releasedOnly = !accessToken
-    let publicAccessToken
-    if (!accessToken && getPublicAccessToken) {
+    if (!accessToken && !publicAccessToken && getPublicAccessToken) {
         publicAccessToken = await getPublicAccessToken()
     }
-    const option = accessToken || publicAccessToken || process.env.ACCESS_TOKEN
+    const option = accessToken || publicAccessToken
         ? {
             auth: {
-                'bearer': accessToken || publicAccessToken || process.env.ACCESS_TOKEN
+                'bearer': accessToken || publicAccessToken
             }
         }
         : {}
 
-    return {option, releasedOnly, token: accessToken || publicAccessToken || process.env.ACCESS_TOKEN}
+    return {
+      option,
+      releasedOnly,
+      token: accessToken || publicAccessToken
+    }
 }
 
 /**
@@ -293,4 +321,37 @@ const transformWaxholmV2NmToVoxel = (coord) => {
   return coord.map((v, idx) => (v - transl[idx]) / voxelDim[idx] )
 }
 
-    
+const getDatasetFromId = async ({ user, kgId, returnAsStream = false }) => {
+  const { option, releasedOnly } = await getUserKGRequestParam({ user })
+  const _url = getKgQuerySingleDatasetUrl({ kgId })
+  if (releasedOnly) _url.searchParams.set('databaseScope', 'RELEASED')
+  if (returnAsStream) return request(_url, option)
+  else return new Promise((resolve, reject) => {
+    request(_url, option, (err, resp, body) => {
+      if (err) return reject(err)
+      if (resp.statusCode >= 400) return reject(resp.statusCode)
+      return resolve(JSON.parse(body))
+    })
+  })
+}
+
+const getDatasetFileAsZip = async ({ user, kgId } = {}) => {
+  if (!kgId) {
+    throw new Error('kgId must be defined')
+  }
+
+  const result = await getDatasetFromId({ user, kgId })
+  const { files } = result
+  const zip = archiver('zip')
+  for (let file of files) {
+    const { name, absolutePath } = file
+    zip.append(request(absolutePath), { name })
+  }
+
+  zip.finalize()
+
+  return zip
+}
+
+exports.getDatasetFromId = getDatasetFromId
+exports.getDatasetFileAsZip = getDatasetFileAsZip
\ No newline at end of file
diff --git a/deploy/package.json b/deploy/package.json
index 72d3c417e28cb9541e4f1c1b0d947875dcda953b..a1d2f4121597df333198cedf3a0be87749356fa2 100644
--- a/deploy/package.json
+++ b/deploy/package.json
@@ -13,6 +13,7 @@
   "author": "",
   "license": "ISC",
   "dependencies": {
+    "archiver": "^3.0.0",
     "body-parser": "^1.19.0",
     "express": "^4.16.4",
     "express-session": "^1.15.6",
diff --git a/src/atlasViewer/atlasViewer.component.ts b/src/atlasViewer/atlasViewer.component.ts
index 628387b0a1a1054db5b5d5316f93e54764309060..954559f4d3a8d232f5732b4cbe7c128e890a443f 100644
--- a/src/atlasViewer/atlasViewer.component.ts
+++ b/src/atlasViewer/atlasViewer.component.ts
@@ -53,7 +53,6 @@ export class AtlasViewer implements OnDestroy, OnInit, AfterViewInit {
   @ViewChild(FixedMouseContextualContainerDirective) rClContextualMenu: FixedMouseContextualContainerDirective
 
   @ViewChild('mobileMenuTabs') mobileMenuTabs: TabsetComponent
-  @ViewChild('publications') publications: TemplateRef<any>
   @ViewChild('sidenav', { read: ElementRef} ) mobileSideNav: ElementRef
 
   /**
@@ -95,8 +94,6 @@ export class AtlasViewer implements OnDestroy, OnInit, AfterViewInit {
 
   public sidePanelOpen$: Observable<boolean>
 
-  dismissToastHandler: any
-
   get toggleMessage(){
     return this.constantsService.toggleMessage
   }
@@ -230,19 +227,6 @@ export class AtlasViewer implements OnDestroy, OnInit, AfterViewInit {
     this.subscriptions.push(
       this.selectedParcellation$.subscribe(parcellation => {
         this.selectedParcellation = parcellation
-
-        if ((this.selectedParcellation['properties'] &&
-            (this.selectedParcellation['properties']['publications'] || this.selectedParcellation['properties']['description']))
-            || (this.selectedTemplate['properties'] &&
-                (this.selectedTemplate['properties']['publications'] || this.selectedTemplate['properties']['description']))) {
-          if (this.dismissToastHandler) {
-            this.dismissToastHandler()
-            this.dismissToastHandler = null
-          }
-          this.dismissToastHandler = this.toastService.showToast(this.publications, {
-              timeout: 7000
-          })
-        }
       })
     )
   }
diff --git a/src/atlasViewer/atlasViewer.template.html b/src/atlasViewer/atlasViewer.template.html
index 8c1054a713c72dfeac5ea24010bbb0cfe3751d3b..5f736ff590d58eb9df5d126cdbd1793914432b11 100644
--- a/src/atlasViewer/atlasViewer.template.html
+++ b/src/atlasViewer/atlasViewer.template.html
@@ -258,17 +258,3 @@
     </ng-container>
   </div>
 </ng-template>
-
-<ng-template #publications >
-  <reference-toast-component *ngIf="selectedTemplate['properties'] || selectedParcellation['properties']"
-          [templateName] = "selectedTemplate['name']? selectedTemplate['name'] : null"
-          [parcellationName] = "selectedParcellation['name']? selectedParcellation['name'] : null"
-          [templateDescription] = "selectedTemplate['properties'] && selectedTemplate['properties']['description']? selectedTemplate['properties']['description'] : null"
-          [parcellationDescription] = "selectedParcellation['properties'] && selectedParcellation['properties']['description']? selectedParcellation['properties']['description'] : null"
-          [templatePublications] = "selectedTemplate['properties'] && selectedTemplate['properties']['publications']? selectedTemplate['properties']['publications']: null"
-          [parcellationPublications] = "selectedParcellation['properties'] && selectedParcellation['properties']['publications']? selectedParcellation['properties']['publications']: null"
-          [parcellationNifti] = "selectedParcellation['properties'] && selectedParcellation['properties']['nifti']? selectedParcellation['properties']['nifti'] : null"
-          [templateExternalLink] ="selectedTemplate['properties'] && selectedTemplate['properties']['externalLink']? selectedTemplate['properties']['externalLink']: null"
-          [parcellationExternalLink] ="selectedParcellation['properties'] && selectedParcellation['properties']['externalLink']? selectedParcellation['properties']['externalLink']: null">
-  </reference-toast-component>
-</ng-template>
\ No newline at end of file
diff --git a/src/components/dropdown/dropdown.component.ts b/src/components/dropdown/dropdown.component.ts
index 78ca10f1e31f217ebb9bbc25f79a76ab9ed540c6..b083c422a10e3895df87642aa9f80832431d7623 100644
--- a/src/components/dropdown/dropdown.component.ts
+++ b/src/components/dropdown/dropdown.component.ts
@@ -1,5 +1,6 @@
 import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy, HostListener, ViewChild, ElementRef } from "@angular/core";
 import { dropdownAnimation } from "./dropdown.animation";
+import { HasExtraButtons, ExraBtnClickEvent } from '../radiolist/radiolist.component'
 
 @Component({
   selector : 'dropdown-component',
@@ -15,7 +16,7 @@ import { dropdownAnimation } from "./dropdown.animation";
 
 export class DropdownComponent{
 
-  @Input() inputArray : any[] = []
+  @Input() inputArray : HasExtraButtons[] = []
   @Input() selectedItem : any | null = null
   @Input() checkSelected: (selectedItem:any, item:any) => boolean = (si,i) => si === i
 
@@ -23,7 +24,7 @@ export class DropdownComponent{
   @Input() activeDisplay : (obj:any|null)=>string = (obj)=>obj ? obj.name : `Please select an item.`
 
   @Output() itemSelected : EventEmitter<any> = new EventEmitter()
-  @Output() listItemButtonClicked: EventEmitter<any> = new EventEmitter()
+  @Output() extraBtnClicked: EventEmitter<ExraBtnClickEvent> = new EventEmitter()
 
   @ViewChild('dropdownToggle',{read:ElementRef}) dropdownToggle : ElementRef
 
diff --git a/src/components/dropdown/dropdown.template.html b/src/components/dropdown/dropdown.template.html
index 0f5866d162c27ff2c8dd284985bf73ac640c05ab..7476c7408c1f340d1e10ecfa4c984af1bacc0f4e 100644
--- a/src/components/dropdown/dropdown.template.html
+++ b/src/components/dropdown/dropdown.template.html
@@ -22,5 +22,5 @@
   [selectedItem]="selectedItem"
   [inputArray]="inputArray"
   [@showState]="openState ? 'show' : 'hide'"
-  (listItemButtonClicked) = listItemButtonClicked.emit($event)>
+  (extraBtnClicked)="extraBtnClicked.emit($event)">
 </radio-list>
diff --git a/src/components/radiolist/radiolist.component.ts b/src/components/radiolist/radiolist.component.ts
index 7b0314f06bb7be2d6230e385465a1a31b216ded0..f1d3558baa125f695941b3a6153ce50945def293 100644
--- a/src/components/radiolist/radiolist.component.ts
+++ b/src/components/radiolist/radiolist.component.ts
@@ -20,20 +20,40 @@ export class RadioList{
   selectedItem: any | null = null
 
   @Input()
-  inputArray: any[] = []
+  inputArray: HasExtraButtons[] = []
 
   @Input()
   ulClass: string = ''
   
   @Input() checkSelected: (selectedItem:any, item:any) => boolean = (si,i) => si === i
 
-  @Output() listItemButtonClicked = new EventEmitter<string>();
+  @Output() extraBtnClicked = new EventEmitter<ExraBtnClickEvent>()
 
-  clickListButton(i) {
-    this.listItemButtonClicked.emit(i)
+  handleExtraBtnClick(extraBtn:ExtraButton, inputItem:any, event:MouseEvent){
+    this.extraBtnClicked.emit({
+      extraBtn,
+      inputItem,
+      event
+    })
   }
 
   overflowText(event) {
     return (event.offsetWidth < event.scrollWidth)
   }
+}
+
+interface ExtraButton{
+  name: string,
+  faIcon: string
+  class?: string
+}
+
+export interface HasExtraButtons{
+  extraButtons?: ExtraButton[]
+}
+
+export interface ExraBtnClickEvent{
+  extraBtn:ExtraButton
+  inputItem:any
+  event:MouseEvent
 }
\ No newline at end of file
diff --git a/src/components/radiolist/radiolist.style.css b/src/components/radiolist/radiolist.style.css
index c6ee787207299fff88b50d856d84dcfb0fd0621d..2d8352e629901669d33dd8df685d0d4eaf0549be 100644
--- a/src/components/radiolist/radiolist.style.css
+++ b/src/components/radiolist/radiolist.style.css
@@ -59,19 +59,6 @@ ul,span.dropdown-item-1
   text-overflow: ellipsis
 }
 
-
-.infoIcon {
-  margin-left: 5px;
-  display: inline-block;
-  border: 1px solid gray;
-  border-radius: 15px;
-  width: 24px;
-  height: 24px;
-  min-width: 24px;
-  cursor: pointer;
-  text-align: center;
-}
-
 :host-context([darktheme="true"]) .radioListMenu {
   border-color: white;
 }
@@ -83,6 +70,6 @@ ul,span.dropdown-item-1
   border-style: solid;
   border-width: 0px 1px 1px 1px;
 }
-:host-context([isMobile="false"]) radioListMenu {
+:host-context([isMobile="false"]) .radioListMenu {
   opacity: 0.8;
 }
\ No newline at end of file
diff --git a/src/components/radiolist/radiolist.template.html b/src/components/radiolist/radiolist.template.html
index eb1d111ba65c6fef07f5e135905ea1af38621c20..d9b7730a761a8073f387af13165462bbb88ce45f 100644
--- a/src/components/radiolist/radiolist.template.html
+++ b/src/components/radiolist/radiolist.template.html
@@ -11,15 +11,18 @@
     (click)="itemSelected.emit({previous: selectedItem, current: input})">
     
     <span class="dropdown-item-1 textSpan"
-          #DropDownText
-          [innerHTML] = "listDisplay(input)"
-          [style.fontWeight] = "checkSelected(selectedItem, input)? 'bold' : ''"
-          [matTooltip]="overflowText(DropDownText)? DropDownText.innerText: ''">
+      #DropDownText
+      [innerHTML]="listDisplay(input)"
+      [ngClass]="checkSelected(selectedItem, input) ? 'font-weight-bold' : ''"
+      [matTooltip]="overflowText(DropDownText)? DropDownText.innerText: ''">
     </span>
 
-    <span *ngIf="input['properties'] && (input['properties']['publications'] || input['properties']['description'])"
-          class="infoIcon align-self-end" (click)="clickListButton(i);$event.stopPropagation()">
-      i
-    </span>
+    <ng-container *ngIf="input.extraButtons as extraButtons">
+      <span *ngFor="let extraBtn of extraButtons"
+        [ngClass]="extraBtn.class"
+        (click)="handleExtraBtnClick(extraBtn, input, $event)">
+        <i [ngClass]="extraBtn.faIcon"></i>
+      </span>
+    </ng-container>
   </li>
 </ul>
\ No newline at end of file
diff --git a/src/components/toast/toast.style.css b/src/components/toast/toast.style.css
index 50624d5c59826c29247dcbfa9f6286229993120a..e39cb38ee456c759dfd5dbe029d11a8c29a37407 100644
--- a/src/components/toast/toast.style.css
+++ b/src/components/toast/toast.style.css
@@ -12,6 +12,7 @@ div[container]
   align-items: center;
   padding : 0.3em 1em 0em 1em;
   pointer-events: all;
+  max-width:80%;
 }
 
 :host-context([darktheme="false"]) div[container]
@@ -36,8 +37,10 @@ div[close]
 {
   display:inline-block;
 }
+
 timer-component
 {
+  flex: 0 0 0.5em;
   margin: 0 -1em;
   height:0.5em;
   width: calc(100% + 2em);
diff --git a/src/components/toast/toast.template.html b/src/components/toast/toast.template.html
index 95032c74b9fbc154f0bd1e7aa9542f3453bf4fa0..7d1eb664845b73687c1be2bf1cdc110b789138ea 100644
--- a/src/components/toast/toast.template.html
+++ b/src/components/toast/toast.template.html
@@ -1,29 +1,45 @@
-<div (mouseenter) = "hover = true" (mouseleave)="hover = false" container>
-  <div message>
-    <ng-template #messageContainer>
+<div
+  class="d-flex flex-column m-auto"
+  (mouseenter)="hover = true"
+  (mouseleave)="hover = false"
+  container>
 
-    </ng-template>
-  </div>
-  <div message
-    [innerHTML]="htmlMessage"
-    *ngIf = "htmlMessage">
-  </div>
-  <div
-    message
-    *ngIf="message && !htmlMessage">
-    {{ message }}
-  </div>
-  <div
-    (click)="dismiss($event)"
-    class="ml-2"
-    *ngIf="dismissable" close>
-    <i class="fas fa-times"></i>
+  <!-- body -->
+  <div class="d-flex flex-row justify-content-between align-items-start">
+
+    <!-- contents -->
+    <div message>
+      <ng-template #messageContainer>
+  
+      </ng-template>
+    </div>
+    <div message
+      [innerHTML]="htmlMessage"
+      *ngIf = "htmlMessage">
+    </div>
+    <div
+      message
+      *ngIf="message && !htmlMessage">
+      {{ message }}
+    </div>
+
+    <!-- dismiss btn -->
+    <div
+      (click)="dismiss($event)"
+      class="m-2"
+      *ngIf="dismissable" close>
+      <i class="fas fa-times"></i>
+    </div>
   </div>
+
+  <!-- timer -->
   <timer-component
+    class="flex-"
     *ngIf="timeout > 0"
     (timerEnd)="dismissed.emit(false)"
     [pause]="hover"
     [timeout]="timeout"
     timer>
   </timer-component>
+
 </div>
\ No newline at end of file
diff --git a/src/main.module.ts b/src/main.module.ts
index daf52879997c91f152b4e8d66cf0b921dd82ad24..1fb66d55c46ea77a249b850a7a349d681d4528f2 100644
--- a/src/main.module.ts
+++ b/src/main.module.ts
@@ -10,6 +10,7 @@ import { GetNamesPipe } from "./util/pipes/getNames.pipe";
 import { CommonModule } from "@angular/common";
 import { GetNamePipe } from "./util/pipes/getName.pipe";
 import { FormsModule } from "@angular/forms";
+import { AngularMaterialModule } from 'src/ui/sharedModules/angularMaterial.module'
 
 import { AtlasViewerDataService } from "./atlasViewer/atlasViewer.dataService.service";
 import { WidgetUnit } from "./atlasViewer/widgetUnit/widgetUnit.component";
@@ -38,7 +39,6 @@ import { ViewerConfiguration } from "./services/state/viewerConfig.store";
 import { FixedMouseContextualContainerDirective } from "./util/directives/FixedMouseContextualContainerDirective.directive";
 import { DatabrowserService } from "./ui/databrowserModule/databrowser.service";
 import { TransformOnhoverSegmentPipe } from "./atlasViewer/onhoverSegment.pipe";
-import { ZipFileDownloadService } from "./services/zipFileDownload.service";
 import {HttpClientModule} from "@angular/common/http";
 import { EffectsModule } from "@ngrx/effects";
 import { UseEffects } from "./services/effect/effect";
@@ -51,6 +51,7 @@ import { UseEffects } from "./services/effect/effect";
     ComponentsModule,
     DragDropModule,
     UIModule,
+    AngularMaterialModule,
     
     ModalModule.forRoot(),
     TooltipModule.forRoot(),
@@ -112,7 +113,6 @@ import { UseEffects } from "./services/effect/effect";
     ToastService,
     AtlasWorkerService,
     AuthService,
-    ZipFileDownloadService,
     
     /**
      * TODO
diff --git a/src/res/css/extra_styles.css b/src/res/css/extra_styles.css
index 2269aed7e731b97f5f97020cce0911ca1df34ea0..f21fd1d70d3865cb60a3555d2789183b46a4aadb 100644
--- a/src/res/css/extra_styles.css
+++ b/src/res/css/extra_styles.css
@@ -340,4 +340,9 @@ markdown-dom pre code
 .text-semi-transparent
 {
   opacity: 0.5;
+}
+
+[darktheme="true"] .card
+{
+  background:none;
 }
\ No newline at end of file
diff --git a/src/res/ext/MNI152.json b/src/res/ext/MNI152.json
index ba1e9e2389c663003907b00898fb93141045c93b..92dd39191c05148ccfcf53949aca8f4ee8c067ef 100644
--- a/src/res/ext/MNI152.json
+++ b/src/res/ext/MNI152.json
@@ -9,12 +9,14 @@
     {
       "name": "JuBrain Cytoarchitectonic Atlas",
       "ngId": "jubrain v17 left",
+      "originDatasets":[{
+        "kgSchema": "minds/core/dataset/v1.0.0",
+        "kgId": "4ac9f0bc-560d-47e0-8916-7b24da9bb0ce"
+      }],
       "properties": {
         "version": "1.0",
         "description": "not yet",
-        "publications": [],
-        "nifti": [{"file":  "jubrain-max-pmap-v22c_space-mnicolin27.nii", "size": "4400000"}],
-        "externalLink":  "https://doi.org/10.25493/8EGG-ZAR"
+        "publications": []
       },
       "regions": [
         {
@@ -5687,8 +5689,11 @@
       "surfaceParcellation": true,
       "ngData": null,
       "name": "Fibre Bundle Atlas - Long Bundle",
+      "originDatasets":[{
+        "kgSchema": "minds/core/dataset/v1.0.0",
+        "kgId": "fcbb049b-edd5-4fb5-acbc-7bf8ee933e24"
+      }],
       "properties": {
-        "externalLink":  "https://doi.org/10.25493/V5BH-P7P"
       },
       "regions": [
         {
@@ -5889,6 +5894,10 @@
       "surfaceParcellation": true,
       "ngData": null,
       "name": "Fibre Bundle Atlas - Short Bundle",
+      "originDatasets":[{
+        "kgSchema": "minds/core/dataset/v1.0.0",
+        "kgId": "f58e4425-6614-4ad9-ac26-5e946b1296cb"
+      }],
       "regions": [
         {
           "name": "Left Hemisphere",
@@ -6919,7 +6928,7 @@
     }
   ],
   "properties": {
-    "name": "MNI 152",
+    "name": "MNI 152 ICBM 2009c Nonlinear Asymmetric",
     "description": "An unbiased non-linear average of multiple subjects from the MNI152 database, which provides high-spatial resolution and signal-to-noise while not being biased towards a single brain (Fonov et al., 2011). This template space is widely used as a reference space in neuroimaging. HBP provides the JuBrain probabilistic cytoarchitectonic atlas (Amunts/Zilles, 2015) as well as a probabilistic atlas of large fibre bundles (Guevara, Mangin et al., 2017) in this space."
   }
 }
diff --git a/src/res/ext/colin.json b/src/res/ext/colin.json
index 985ebb575ae1051fd9cc06ab67e3339ac4ebf392..beb97256a249d7d24646d029876bf5abe8e4f68b 100644
--- a/src/res/ext/colin.json
+++ b/src/res/ext/colin.json
@@ -9,12 +9,14 @@
     {
       "name": "JuBrain Cytoarchitectonic Atlas",
       "ngId": "jubrain colin v17 left",
+      "originDatasets":[{
+        "kgSchema": "minds/core/dataset/v1.0.0",
+        "kgId": "4ac9f0bc-560d-47e0-8916-7b24da9bb0ce"
+      }],
       "properties": {
         "version": "1.0",
         "description": "not yet",
-        "publications": [],
-        "nifti": [{"file":  "jubrain-max-pmap-v22c_space-mnicolin27.nii", "size": "4400000"}],
-        "externalLink":  "https://doi.org/10.25493/8EGG-ZAR"
+        "publications": []
       },
       "regions": [
         {
diff --git a/src/services/toastService.service.ts b/src/services/toastService.service.ts
index 6c755753f0165ba18eca5b3e4e73f40298592e1f..35ac359717662d07cb3172c5d37542f7e1ec9596 100644
--- a/src/services/toastService.service.ts
+++ b/src/services/toastService.service.ts
@@ -1,10 +1,12 @@
 import { Injectable, TemplateRef } from "@angular/core";
+import { ToastHandler } from "src/util/pluginHandlerClasses/toastHandler";
 
 @Injectable({
   providedIn : 'root'
 })
 export class ToastService{
   showToast: (message: string | TemplateRef<any>, config?: Partial<ToastConfig>)=>()=>void
+  getToastHandler: () => ToastHandler
 }
 
 export interface ToastConfig{
diff --git a/src/services/zipFileDownload.service.ts b/src/services/zipFileDownload.service.ts
deleted file mode 100644
index 68131c4bf6932e0dd8df8691936b3bd0d3563738..0000000000000000000000000000000000000000
--- a/src/services/zipFileDownload.service.ts
+++ /dev/null
@@ -1,58 +0,0 @@
-import { Injectable } from "@angular/core";
-import {HttpClient} from "@angular/common/http";
-import {AtlasViewerConstantsServices} from "src/atlasViewer/atlasViewer.constantService.service";
-import {map} from "rxjs/operators";
-
-@Injectable({ providedIn: 'root' })
-export class ZipFileDownloadService {
-
-    constructor(private httpClient: HttpClient, private constantService: AtlasViewerConstantsServices) {}
-
-    downloadZip(publicationsText, fileName, niiFiles) {
-        const correctedName = fileName.replace(/[|&;$%@"<>()+,/]/g, "")
-        return this.httpClient.post(this.constantService.backendUrl + 'datasets/downloadParcellationThemself', {
-                fileName: correctedName,
-                publicationsText: publicationsText,
-                niiFiles: niiFiles === 0 ? null : niiFiles
-            },{responseType: "text"}
-        ).pipe(
-            map (data => {
-                this.downloadFile(data, correctedName)
-            })
-        )
-    }
-
-    downloadFile(data, fileName) {
-        const contentType = 'application/zip';
-        const b64Data = data
-
-        const b64toBlob = (b64Data, contentType='', sliceSize=512) => {
-            const byteCharacters = atob(b64Data);
-            const byteArrays = [];
-
-            for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
-                const slice = byteCharacters.slice(offset, offset + sliceSize);
-
-                const byteNumbers = new Array(slice.length);
-                for (let i = 0; i < slice.length; i++) {
-                    byteNumbers[i] = slice.charCodeAt(i);
-                }
-
-                const byteArray = new Uint8Array(byteNumbers);
-                byteArrays.push(byteArray);
-            }
-
-            const blob = new Blob(byteArrays, {type: contentType});
-            return blob;
-        }
-
-        const blob = b64toBlob(b64Data, contentType);
-        const url= window.URL.createObjectURL(blob);
-        const anchor = document.createElement("a");
-        anchor.download = fileName + '.zip';
-        anchor.href = url;
-        anchor.click();
-    }
-
-
-}
\ No newline at end of file
diff --git a/src/ui/databrowserModule/databrowser.module.ts b/src/ui/databrowserModule/databrowser.module.ts
index 1238aa758a99074e33dfdfaccd0daf488e82cbc7..9868e3f2c55553d316e56b6f2dabbae9b0c83087 100644
--- a/src/ui/databrowserModule/databrowser.module.ts
+++ b/src/ui/databrowserModule/databrowser.module.ts
@@ -21,6 +21,9 @@ import { AtlasViewerConstantsServices } from "src/atlasViewer/atlasViewer.consta
 import { PopoverModule } from "ngx-bootstrap/popover";
 import { UtilModule } from "src/util/util.module";
 import { AggregateArrayIntoRootPipe } from "./util/aggregateArrayIntoRoot.pipe";
+import { KgSingleDatasetService } from "./kgSingleDatasetService.service"
+import { SingleDatasetView } from './singleDataset/singleDataset.component'
+import { AngularMaterialModule } from 'src/ui/sharedModules/angularMaterial.module'
 
 @NgModule({
   imports:[
@@ -29,6 +32,7 @@ import { AggregateArrayIntoRootPipe } from "./util/aggregateArrayIntoRoot.pipe";
     ComponentsModule,
     FormsModule,
     UtilModule,
+    AngularMaterialModule,
     TooltipModule.forRoot(),
     PopoverModule.forRoot()
   ],
@@ -41,6 +45,7 @@ import { AggregateArrayIntoRootPipe } from "./util/aggregateArrayIntoRoot.pipe";
     RadarChart,
     LineChart,
     DedicatedViewer,
+    SingleDatasetView,
 
     /**
      * pipes
@@ -52,10 +57,14 @@ import { AggregateArrayIntoRootPipe } from "./util/aggregateArrayIntoRoot.pipe";
     AggregateArrayIntoRootPipe
   ],
   exports:[
-    DataBrowser
+    DataBrowser,
+    SingleDatasetView
   ],
   entryComponents:[
     DataBrowser
+  ],
+  providers: [
+    KgSingleDatasetService
   ]
   /**
    * shouldn't need bootstrap, so no need for browser module
diff --git a/src/ui/databrowserModule/kgSingleDatasetService.service.ts b/src/ui/databrowserModule/kgSingleDatasetService.service.ts
new file mode 100644
index 0000000000000000000000000000000000000000..31738eee7c4f55724f35c36dae69372b629b2b18
--- /dev/null
+++ b/src/ui/databrowserModule/kgSingleDatasetService.service.ts
@@ -0,0 +1,48 @@
+import { Injectable } from "@angular/core";
+import { AtlasViewerConstantsServices } from "src/atlasViewer/atlasViewer.constantService.service"
+
+@Injectable({ providedIn: 'root' })
+export class KgSingleDatasetService {
+
+  constructor(private constantService: AtlasViewerConstantsServices) {
+  }
+
+  public getInfoFromKg({ kgId, kgSchema }: KgQueryInterface) {
+    const _url = new URL(`${this.constantService.backendUrl}datasets/kgInfo`)
+    const searchParam = _url.searchParams
+    searchParam.set('kgSchema', kgSchema)
+    searchParam.set('kgId', kgId)
+    return fetch(_url.toString())
+      .then(res => {
+        if (res.status >= 400) throw new Error(res.status.toString())
+        return res.json()
+      })
+  }
+
+  public downloadZipFromKg({ kgSchema, kgId } : KgQueryInterface, filename = 'download'){
+    const _url = new URL(`${this.constantService.backendUrl}datasets/downloadKgFiles`)
+    const searchParam = _url.searchParams
+    searchParam.set('kgSchema', kgSchema)
+    searchParam.set('kgId', kgId)
+    return fetch(_url.toString())
+      .then(res => {
+        if (res.status >= 400) throw new Error(res.status.toString())
+        return res.blob()
+      })
+      .then(data => this.simpleDownload(data, filename))
+  }
+
+  public simpleDownload(data, filename) {
+    const blob = new Blob([data], { type: 'application/zip'})
+    const url= window.URL.createObjectURL(blob);
+    const anchor = document.createElement("a");
+    anchor.download = filename + '.zip';
+    anchor.href = url;
+    anchor.click();
+  }
+}
+
+interface KgQueryInterface{
+  kgSchema: string
+  kgId: string
+}
\ No newline at end of file
diff --git a/src/ui/databrowserModule/singleDataset/singleDataset.component.ts b/src/ui/databrowserModule/singleDataset/singleDataset.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..997ed303fdfca77f1d6abce2241bf38837945e48
--- /dev/null
+++ b/src/ui/databrowserModule/singleDataset/singleDataset.component.ts
@@ -0,0 +1,106 @@
+import { Component, Input, OnInit, ChangeDetectionStrategy, ChangeDetectorRef } from "@angular/core";
+import { KgSingleDatasetService } from "../kgSingleDatasetService.service";
+import { Publication, File } from 'src/services/state/dataStore.store'
+
+@Component({
+  selector: 'single-dataset-view',
+  templateUrl: './singleDataset.template.html',
+  styleUrls: [
+    `./singleDataset.style.css`
+  ],
+  changeDetection: ChangeDetectionStrategy.OnPush
+})
+export class SingleDatasetView implements OnInit {
+
+  /**
+   * the name/desc/publications are placeholder/fallback entries
+   * while the actual data is being loaded from KG with kgSchema and kgId
+   */
+  @Input() name?: string
+  @Input() description?: string
+  @Input() publications?: Publication[]
+
+  @Input() kgSchema?: string
+  @Input() kgId?: string
+
+  /**
+   * sic!
+   */
+  private kgReference: string[] = []
+  private files: File[] = []
+  private methods: string[] = []
+  /**
+   * sic!
+   */
+  private parcellationRegion: { name: string }[]
+
+  private error: string = null
+
+  public fetchingSingleInfoInProgress = false
+  public downloadInProgress = false
+
+  constructor(
+    private singleDatasetService: KgSingleDatasetService,
+    private cdr: ChangeDetectorRef
+  ){}
+
+  ngOnInit() {
+    const { kgId, kgSchema } = this
+
+    if (!kgSchema || !kgId) return
+    this.fetchingSingleInfoInProgress = true
+    this.singleDatasetService.getInfoFromKg({
+      kgId,
+      kgSchema
+    })
+      .then(({ files, publications, name, description, kgReference}) => {
+        /**
+         * TODO dataset specific
+         */
+        this.name = name
+        this.description = description
+        this.kgReference = kgReference
+        this.publications = publications
+        this.files = files
+
+        this.cdr.markForCheck()
+      })
+      .catch(e => {
+        this.error = e
+      })
+      .finally(() => {
+        this.fetchingSingleInfoInProgress = false
+      })
+  }
+
+  get downloadEnabled() {
+    return this.kgSchema && this.kgId
+  }
+
+  get appendedKgReferences() {
+    return this.kgReference.map(v => `https://doi.org/${v}`)
+  }
+
+  get numOfFiles(){
+    return this.files
+      ? this.files.length
+      : null
+  }
+
+  get totalFileByteSize(){
+    return this.files
+      ? this.files.reduce((acc, curr) => acc + curr.byteSize, 0)
+      : null
+  }
+
+  downloadZipFromKg() {
+    this.downloadInProgress = true
+    const { kgId, kgSchema }  = this
+    this.singleDatasetService.downloadZipFromKg({
+      kgId,
+      kgSchema
+    })
+      .catch(console.error)
+      .finally(() => this.downloadInProgress = false)
+  }
+}
diff --git a/src/ui/databrowserModule/singleDataset/singleDataset.style.css b/src/ui/databrowserModule/singleDataset/singleDataset.style.css
new file mode 100644
index 0000000000000000000000000000000000000000..9c4f33e35402143057541d30e4c76fe566cba76d
--- /dev/null
+++ b/src/ui/databrowserModule/singleDataset/singleDataset.style.css
@@ -0,0 +1,4 @@
+:host
+{
+  text-align: left
+}
\ No newline at end of file
diff --git a/src/ui/databrowserModule/singleDataset/singleDataset.template.html b/src/ui/databrowserModule/singleDataset/singleDataset.template.html
new file mode 100644
index 0000000000000000000000000000000000000000..8467234746854c190a08a2d9925176be62de1ba8
--- /dev/null
+++ b/src/ui/databrowserModule/singleDataset/singleDataset.template.html
@@ -0,0 +1,54 @@
+<div class="card">
+  <div class="card-body">
+
+    <!-- title -->
+    <h5 class="card-title">
+      {{ name }}
+    </h5>
+
+    <!-- description -->
+    <p class="card-text">
+      {{ description }}
+    </p>
+
+    <hr>
+    <!-- publications -->
+    <a
+      *ngFor="let publication of publications"
+      [href]="'https://doi.org/' + publication.doi"
+      target="_blank">
+      {{ publication.cite }}
+    </a>
+
+    <!-- footer -->
+    <div class="d-flex justify-content-end">
+
+      <!-- explore -->
+      <a
+        *ngFor="let kgRef of appendedKgReferences"
+        class="m-2"
+        mat-raised-button
+        color="primary"
+        [href]="kgRef"
+        target="_blank">
+        <span>
+          Explore
+        </span>
+        <i class="fas fa-external-link-alt"></i>
+      </a>
+
+      <!-- download -->
+      <a
+        class="m-2"
+        *ngIf="files.length > 0"
+        mat-raised-button
+        color="primary">
+        <span>
+          Download Zip
+        </span>
+        <span *ngIf="false">({{ numOfFiles }} files ~ {{ totalFileByteSize / 1e6 | number: '.1-2' }} MB)</span>
+        <i class="fas" [ngClass]="!downloadInProgress? 'fa-download' :'fa-spinner fa-pulse'"></i>
+      </a>
+    </div>
+  </div>
+</div>
\ No newline at end of file
diff --git a/src/ui/referenceToast/referenceToast.component.ts b/src/ui/referenceToast/referenceToast.component.ts
deleted file mode 100644
index 6ac6485407b43d7a7ce3416868b95731b2c5e06b..0000000000000000000000000000000000000000
--- a/src/ui/referenceToast/referenceToast.component.ts
+++ /dev/null
@@ -1,93 +0,0 @@
-import { Component, Input, OnInit } from "@angular/core";
-import { ZipFileDownloadService } from "src/services/zipFileDownload.service";
-
-@Component({
-    selector : 'reference-toast-component',
-    templateUrl : './referenceToast.template.html',
-    styleUrls : [
-        `./referenceToast.style.css`
-    ],
-})
-export class ReferenceToastComponent implements OnInit{
-    @Input() templateName? : string
-    @Input() parcellationName? : string
-    @Input() templateDescription? : string
-    @Input() parcellationDescription? : string
-    @Input() templatePublications? : any
-    @Input() parcellationPublications? : any
-    @Input() parcellationNifti? : any
-    @Input() templateExternalLink? : any
-    @Input() parcellationExternalLink? : any
-
-    downloadingProcess = false
-    niiFileSize = 0
-
-    constructor(private zipFileDownloadService: ZipFileDownloadService) {}
-
-    ngOnInit(): void {
-        if (this.parcellationNifti) {
-            this.parcellationNifti.forEach(nii => {
-                this.niiFileSize += nii['size']
-            })
-        }
-    }
-
-    downloadPublications() {
-        this.downloadingProcess = true
-
-        let fileName = ''
-        let publicationsText = ''
-
-        if (this.templatePublications || this.templateDescription) {
-            fileName += this.templateName? this.templateName : 'Template'
-
-            if (this.templateDescription) {
-                publicationsText += this.templateName + '\r\n'
-                this.templateDescription.split(" ").forEach((word, index) => {
-                    publicationsText += word + ' '
-                    if (index && index%15 === 0) publicationsText += '\r\n'
-                })
-                publicationsText += '\r\n'
-            }
-
-            if (this.templatePublications) {
-                if (!this.templateDescription) publicationsText += this.templateName
-                publicationsText += ' Publications:\r\n'
-                this.templatePublications.forEach((tp, i) => {
-                    publicationsText += '\t' + (i+1) + '. ' + tp['citation'] + ' - ' + tp['doi'] + '\r\n'
-                })
-            }
-        }
-
-        if (this.parcellationPublications || this.parcellationDescription) {
-            if (this.templateName) fileName += ' - '
-            fileName += this.parcellationName? this.parcellationName : 'Parcellation'
-            if (this.templateDescription || this.templatePublications) publicationsText += '\r\n\r\n'
-
-            if (this.parcellationDescription) {
-                publicationsText += this.parcellationName + '\r\n'
-                this.parcellationDescription.split(" ").forEach((word, index) => {
-                    publicationsText += word + ' '
-                    if (index && index%15 === 0) publicationsText += '\r\n'
-                })
-                publicationsText += '\r\n'
-            }
-
-            if (this.parcellationPublications) {
-                if (!this.parcellationDescription) publicationsText += this.parcellationName
-                publicationsText += ' Publications:\r\n'
-                this.parcellationPublications.forEach((pp, i) => {
-                    publicationsText += '\t' + (i+1) + '. ' + pp['citation'] + ' - ' + pp['doi'] + '\r\n'
-                })
-            }
-        }
-
-        this.zipFileDownloadService.downloadZip(
-            publicationsText,
-            fileName,
-            this.parcellationNifti? this.parcellationNifti : 0).subscribe(data => {
-            this.downloadingProcess = false
-        })
-        publicationsText = ''
-    }
-}
diff --git a/src/ui/referenceToast/referenceToast.style.css b/src/ui/referenceToast/referenceToast.style.css
deleted file mode 100644
index cf52094f562a63ff2034df2ee50b64240b889c00..0000000000000000000000000000000000000000
--- a/src/ui/referenceToast/referenceToast.style.css
+++ /dev/null
@@ -1,14 +0,0 @@
-.timerToast {
-    max-width: 700px;
-    max-height: 500px;
-    padding-right: 10px;
-    overflow-y: auto;
-}
-
-.download-buttons-panel {
-    align-self: flex-end;
-}
-.downloadPublications {
-    margin: 5px;
-    outline: none;
-}
\ No newline at end of file
diff --git a/src/ui/referenceToast/referenceToast.template.html b/src/ui/referenceToast/referenceToast.template.html
deleted file mode 100644
index b35297ee1517389bd753fa41005dd75ac627d449..0000000000000000000000000000000000000000
--- a/src/ui/referenceToast/referenceToast.template.html
+++ /dev/null
@@ -1,36 +0,0 @@
-<div class="timerToast d-flex flex-column">
-    <div *ngIf="templateDescription">
-        <p *ngIf="templateName">{{templateName}}</p>
-        <p class="text-justify">{{templateDescription}}</p>
-    </div>
-    <div *ngIf="templatePublications">
-        <p>Publication(s)</p>
-        <div *ngFor="let tp of templatePublications" class="text-justify">
-            <a [href]="tp['doi']" target="_blank">{{tp['citation']}}</a>
-        </div>
-        <div class="d-flex justify-content-end">
-            <a class="align-self-end" *ngIf="templateExternalLink" href="{{templateExternalLink}}" target="_blank"><button mat-raised-button color="primary" class="downloadPublications">Explore &nbsp;<i class="fas fa-external-link-alt"></i></button></a>
-        </div>
-        <hr *ngIf="parcellationPublications">
-    </div>
-    <div *ngIf="parcellationDescription">
-        <p *ngIf="parcellationName">{{parcellationName}}</p>
-        <p class="text-justify">{{parcellationDescription}}</p>
-    </div>
-
-    <div *ngIf="parcellationPublications">
-        <p>Publication(s)</p>
-        <div *ngFor="let pp of parcellationPublications" class="text-justify">
-            <a [href]="pp['doi']" target="_blank">{{pp['citation']}}</a>
-        </div>
-    </div>
-
-    <div class="align-self-end">
-        <a *ngIf="parcellationExternalLink" href="{{parcellationExternalLink}}" target="_blank"><button mat-raised-button color="primary" class="downloadPublications">Explore &nbsp;<i class="fas fa-external-link-alt"></i></button></a>
-        <button mat-raised-button color="primary" class="downloadPublications" (click)="downloadPublications()" [disabled] = "downloadingProcess" >
-            Download &nbsp;
-            <span *ngIf="niiFileSize > 0">(.nii {{niiFileSize/1000000 | number:'.1-2'}} Mb) &nbsp;</span>
-            <i class="fas" [ngClass]="!downloadingProcess? 'fa-download' :'fa-spinner fa-pulse'"></i>
-        </button>
-    </div>
-</div>
\ No newline at end of file
diff --git a/src/ui/signinBanner/signinBanner.components.ts b/src/ui/signinBanner/signinBanner.components.ts
index 80fc79fb55464aaabb80b0afdaf40b06e70f46a3..93c18c3f7bec8f44f1d82403524ad24f052c64fd 100644
--- a/src/ui/signinBanner/signinBanner.components.ts
+++ b/src/ui/signinBanner/signinBanner.components.ts
@@ -1,13 +1,14 @@
-import {Component, ChangeDetectionStrategy, OnDestroy, OnInit, Input, ViewChild, TemplateRef} from "@angular/core";
+import {Component, ChangeDetectionStrategy, OnDestroy, OnInit, Input, ViewChild, TemplateRef } from "@angular/core";
 import { AtlasViewerConstantsServices } from "src/atlasViewer/atlasViewer.constantService.service";
 import { AuthService, User } from "src/services/auth.service";
 import { Store, select } from "@ngrx/store";
 import { ViewerConfiguration } from "src/services/state/viewerConfig.store";
-import { Subscription, Observable } from "rxjs";
+import { Subscription, Observable, merge, Subject, interval } from "rxjs";
 import { safeFilter, isDefined, NEWVIEWER, SELECT_REGIONS, SELECT_PARCELLATION, CHANGE_NAVIGATION } from "src/services/stateStore.service";
-import { map, filter, distinctUntilChanged } from "rxjs/operators";
+import { map, filter, distinctUntilChanged, bufferTime, delay, share, tap } from "rxjs/operators";
 import { regionFlattener } from "src/util/regionFlattener";
 import { ToastService } from "src/services/toastService.service";
+import { getSchemaIdFromName } from "src/util/pipes/templateParcellationDecoration.pipe";
 
 const compareParcellation = (o, n) => o.name === n.name
 
@@ -36,9 +37,10 @@ export class SigninBanner implements OnInit, OnDestroy{
 
   @ViewChild('publicationTemplate', {read:TemplateRef}) publicationTemplate: TemplateRef<any>
 
-  dismissToastHandler: any
-  chosenTemplateIndex: number
-  chosenParcellationIndex: number
+  public focusedDatasets$: Observable<any[]>
+  private userFocusedDataset$: Subject<any> = new Subject()
+  public focusedDatasets: any[] = []
+  private dismissToastHandler: () => void
 
   constructor(
     private constantService: AtlasViewerConstantsServices,
@@ -54,14 +56,15 @@ export class SigninBanner implements OnInit, OnDestroy{
 
     this.selectedTemplate$ = this.store.pipe(
       select('viewerState'),
-      filter(state => isDefined(state) && isDefined(state.templateSelected)),
-      distinctUntilChanged((o, n) => o.templateSelected.name === n.templateSelected.name),
-      map(state => state.templateSelected)
+      select('templateSelected'),
+      filter(v => !!v),
+      distinctUntilChanged((o, n) => o.name === n.name),
     )
 
     this.selectedParcellation$ = this.store.pipe(
       select('viewerState'),
       select('parcellationSelected'),
+      filter(v => !!v)
     )
 
     this.selectedRegions$ = this.store.pipe(
@@ -70,6 +73,43 @@ export class SigninBanner implements OnInit, OnDestroy{
       map(state => state.regionsSelected),
       distinctUntilChanged((arr1, arr2) => arr1.length === arr2.length && (arr1 as any[]).every((item, index) => item.name === arr2[index].name))
     )
+
+    this.focusedDatasets$ = merge(
+      this.selectedTemplate$.pipe(
+        map(v => [v])
+      ),
+      this.selectedParcellation$.pipe(
+        distinctUntilChanged((o, n) => o.name === n.name),
+        map(p => {
+          if (!p.originDatasets || !p.originDatasets.map) return [p]
+          return p.originDatasets.map(od => {
+            return {
+              ...p,
+              ...od
+            }
+          })
+        })
+      ),
+      this.userFocusedDataset$.pipe(
+        filter(v => !!v)
+      )
+    ).pipe(
+      bufferTime(100),
+      map(arrOfArr => arrOfArr.reduce((acc, curr) => acc.concat(curr), [])),
+      filter(arr => arr.length > 0),
+      /**
+       * merge properties field with the root level
+       * with the prop in properties taking priority
+       */
+      map(arr => arr.map(item => {
+        const { properties } = item
+        return {
+          ...item,
+          ...properties
+        }
+      })),
+      share()
+    )
   }
 
   ngOnInit(){
@@ -80,7 +120,28 @@ export class SigninBanner implements OnInit, OnDestroy{
       })
     )
     this.subscriptions.push(
-        this.selectedTemplate$.subscribe(template => this.selectedTemplate = template)
+      this.selectedTemplate$.subscribe(template => this.selectedTemplate = template)
+    )
+
+    this.subscriptions.push(
+      this.focusedDatasets$.subscribe(() => {
+        if (this.dismissToastHandler) this.dismissToastHandler()
+      })
+    )
+
+    this.subscriptions.push(
+      this.focusedDatasets$.pipe(
+        /**
+         * creates the illusion that the toast complete disappears before reappearing
+         */
+        delay(100)
+      ).subscribe(arr => {
+        this.focusedDatasets = arr
+        this.dismissToastHandler = this.toastService.showToast(this.publicationTemplate, {
+          dismissable: true,
+          timeout:7000
+        })
+      })
     )
   }
 
@@ -89,8 +150,7 @@ export class SigninBanner implements OnInit, OnDestroy{
   }
 
   changeTemplate({ current, previous }){
-    if (previous && current && current.name === previous.name)
-      return
+    if (previous && current && current.name === previous.name) return
     this.store.dispatch({
       type: NEWVIEWER,
       selectTemplate: current,
@@ -101,8 +161,7 @@ export class SigninBanner implements OnInit, OnDestroy{
   changeParcellation({ current, previous }){
     const { ngId: prevNgId} = previous
     const { ngId: currNgId} = current
-    if (prevNgId === currNgId)
-      return
+    if (prevNgId === currNgId) return
     this.store.dispatch({
       type: SELECT_PARCELLATION,
       selectParcellation: current
@@ -111,8 +170,7 @@ export class SigninBanner implements OnInit, OnDestroy{
 
   // TODO handle mobile
   handleRegionClick({ mode = 'single', region }){
-    if (!region)
-      return
+    if (!region) return
     
     /**
      * single click on region hierarchy => toggle selection
@@ -180,17 +238,23 @@ export class SigninBanner implements OnInit, OnDestroy{
     })
   }
 
-  showInfoToast($event, toastType) {
-    this.chosenTemplateIndex = toastType === 'template'? $event : null
-    this.chosenParcellationIndex = toastType === 'parcellation'? $event : null
+  handleExtraBtnClicked(event, toastType: 'parcellation' | 'template'){
+    const { 
+      extraBtn,
+      inputItem,
+      event: extraBtnClickEvent
+    } = event
 
-    if (this.dismissToastHandler) {
-      this.dismissToastHandler()
-      this.dismissToastHandler = null
-    }
-    this.dismissToastHandler = this.toastService.showToast(this.publicationTemplate, {
-      timeout: 7000
-    })
+    const { name } = extraBtn
+    const { kgSchema, kgId } = getSchemaIdFromName(name)
+
+    this.userFocusedDataset$.next([{
+      ...inputItem,
+      kgSchema,
+      kgId
+    }])
+
+    extraBtnClickEvent.stopPropagation()
   }
 
   get isMobile(){
diff --git a/src/ui/signinBanner/signinBanner.template.html b/src/ui/signinBanner/signinBanner.template.html
index a0f0c16be66195c163ae89b3f2c7bc2d9320e1c9..01000c0db06f00e056198a820bcde53ddc3397b0 100644
--- a/src/ui/signinBanner/signinBanner.template.html
+++ b/src/ui/signinBanner/signinBanner.template.html
@@ -7,8 +7,9 @@
     (itemSelected)="changeTemplate($event)"
     [activeDisplay]="displayActiveTemplate"
     [selectedItem]="selectedTemplate$ | async"
-    [inputArray]="loadedTemplates$ | async | filterNull"
+    [inputArray]="loadedTemplates$ | async | filterNull | templateParcellationsDecorationPipe"
     [ngClass]="isMobile ? flexItemIsMobileClass : flexItemIsDesktopClass"
+    (extraBtnClicked)="handleExtraBtnClicked($event, 'template')"
     (listItemButtonClicked)="showInfoToast($event, 'template')">
   </dropdown-component>
 
@@ -19,9 +20,10 @@
       [checkSelected]="compareParcellation"
       [activeDisplay]="displayActiveParcellation"
       [selectedItem]="selectedParcellation"
-      [inputArray]="selectedTemplate.parcellations"
+      [inputArray]="selectedTemplate.parcellations | templateParcellationsDecorationPipe"
       [ngClass]="isMobile ? flexItemIsMobileClass : flexItemIsDesktopClass"
-      (listItemButtonClicked)="showInfoToast($event, 'parcellation')">>
+      (extraBtnClicked)="handleExtraBtnClicked($event, 'parcellation')"
+      (listItemButtonClicked)="showInfoToast($event, 'parcellation')">
 
     </dropdown-component>
     <region-hierarchy
@@ -76,28 +78,16 @@
   </div>
 </div>
 
+<!-- TODO somehow, using async pipe here does not work -->
+<!-- maybe have something to do with bufferTime, and that it replays from the beginning?  -->
 <ng-template #publicationTemplate>
-  <div *ngIf="loadedTemplates$ | async as loadedTemplates">
-    <div *ngIf="chosenTemplateIndex !== null; else parcellationToast">
-      <reference-toast-component *ngIf="loadedTemplates[chosenTemplateIndex]['properties'] && (loadedTemplates[chosenTemplateIndex]['properties']['description'] || loadedTemplates[chosenTemplateIndex]['properties']['publications'])"
-                               [templateName] = "loadedTemplates[chosenTemplateIndex]['name'] ? loadedTemplates[chosenTemplateIndex]['name'] : null"
-                               [templateDescription] = "loadedTemplates[chosenTemplateIndex]['properties']['description']? loadedTemplates[chosenTemplateIndex]['properties']['description'] : null"
-                               [templatePublications] = "loadedTemplates[chosenTemplateIndex]['properties']['publications']? loadedTemplates[chosenTemplateIndex]['properties']['publications']: null"
-                               [templateExternalLink] ="loadedTemplates[chosenTemplateIndex]['properties']['externalLink']? loadedTemplates[chosenTemplateIndex]['properties']['externalLink']: null">
-      </reference-toast-component>
-    </div>
-    <ng-template #parcellationToast>
-      <div *ngIf="(selectedTemplate$ | async) as selectedTemplate">
-        <div *ngIf="selectedTemplate.parcellations[chosenParcellationIndex]['properties'] && (selectedTemplate.parcellations[chosenParcellationIndex]['properties']['description'] || selectedTemplate.parcellations[chosenParcellationIndex]['properties']['publications'])">
-        <reference-toast-component
-              [parcellationName] = "selectedTemplate.parcellations[chosenParcellationIndex]['name']? selectedTemplate.parcellations[chosenParcellationIndex]['name'] : null"
-              [parcellationDescription] = "selectedTemplate.parcellations[chosenParcellationIndex]['properties']['description']? selectedTemplate.parcellations[chosenParcellationIndex]['properties']['description'] : null"
-              [parcellationPublications] = "selectedTemplate.parcellations[chosenParcellationIndex]['properties']['publications']? selectedTemplate.parcellations[chosenParcellationIndex]['properties']['publications']: null"
-              [parcellationNifti] = "selectedTemplate.parcellations[chosenParcellationIndex]['properties']['nifti']? selectedTemplate.parcellations[chosenParcellationIndex]['properties']['nifti'] : null"
-              [parcellationExternalLink] ="selectedTemplate.parcellations[chosenParcellationIndex]['properties']['externalLink']? selectedTemplate.parcellations[chosenParcellationIndex]['properties']['externalLink']: null">
-        </reference-toast-component>
-        </div>
-      </div>
-    </ng-template>
-  </div>
+  <single-dataset-view
+    *ngFor="let focusedDataset of focusedDatasets"
+    [name]="focusedDataset.name"
+    [description]="focusedDataset.description"
+    [publications]="focusedDataset.publications"
+    [kgSchema]="focusedDataset.kgSchema"
+    [kgId]="focusedDataset.kgId">
+    
+  </single-dataset-view>
 </ng-template>
\ No newline at end of file
diff --git a/src/ui/ui.module.ts b/src/ui/ui.module.ts
index 868912b551cb0c72e77aac85ebca80204d0abf5d..21f85b35e4777115981aa10a249c18bfc6f2cb97 100644
--- a/src/ui/ui.module.ts
+++ b/src/ui/ui.module.ts
@@ -45,8 +45,8 @@ import { FilterNameBySearch } from "./regionHierachy/filterNameBySearch.pipe";
 import { StatusCardComponent } from "./nehubaContainer/statusCard/statusCard.component";
 import { CookieAgreement } from "./cookieAgreement/cookieAgreement.component";
 import { KGToS } from "./kgtos/kgtos.component";
-import { AngularMaterialModule } from "./sharedModules/angularMaterial.module";
-import {ReferenceToastComponent} from "src/ui/referenceToast/referenceToast.component";
+import { AngularMaterialModule } from 'src/ui/sharedModules/angularMaterial.module'
+import { TemplateParcellationsDecorationPipe } from "src/util/pipes/templateParcellationDecoration.pipe";
 
 
 @NgModule({
@@ -83,7 +83,6 @@ import {ReferenceToastComponent} from "src/ui/referenceToast/referenceToast.comp
     StatusCardComponent,
     CookieAgreement,
     KGToS,
-    ReferenceToastComponent,
 
     /* pipes */
     GroupDatasetByRegion,
@@ -97,6 +96,7 @@ import {ReferenceToastComponent} from "src/ui/referenceToast/referenceToast.comp
     FilterNullPipe,
     FilterNgLayer,
     FilterNameBySearch,
+    TemplateParcellationsDecorationPipe,
 
     /* directive */
     DownloadDirective,
@@ -127,9 +127,7 @@ import {ReferenceToastComponent} from "src/ui/referenceToast/referenceToast.comp
     SigninModal,
     CookieAgreement,
     KGToS,
-    AngularMaterialModule,
-    StatusCardComponent,
-    ReferenceToastComponent
+    StatusCardComponent
   ]
 })
 
diff --git a/src/util/directives/toastContainer.directive.ts b/src/util/directives/toastContainer.directive.ts
index f32c5346226341b32e88d1ecacfcb658589871a2..d80740c2e549c68827bc8d296c8282ff49689e13 100644
--- a/src/util/directives/toastContainer.directive.ts
+++ b/src/util/directives/toastContainer.directive.ts
@@ -1,4 +1,4 @@
-import { Directive, ViewContainerRef, ComponentFactoryResolver, TemplateRef, ComponentRef } from '@angular/core'
+import { Directive, ViewContainerRef,ComponentFactory, ComponentFactoryResolver, TemplateRef, ComponentRef } from '@angular/core'
 import { ToastService, defaultToastConfig } from 'src/services/toastService.service';
 import { ToastComponent } from 'src/components/toast/toast.component';
 import { AtlasViewerAPIServices } from 'src/atlasViewer/atlasViewer.apiService.service';
@@ -9,13 +9,16 @@ import { ToastHandler } from '../pluginHandlerClasses/toastHandler';
 })
 
 export class ToastContainerDirective{
+
+  private toastComponentFactory: ComponentFactory<ToastComponent>
+
   constructor(
     private viewContainerRef: ViewContainerRef,
     private toastService: ToastService,
     private cfr: ComponentFactoryResolver,
     private apiService: AtlasViewerAPIServices
   ){
-    const toastComponentFactory = this.cfr.resolveComponentFactory(ToastComponent)
+    this.toastComponentFactory = this.cfr.resolveComponentFactory(ToastComponent)
     
     this.toastService.showToast = (message, config = {}) => {
 
@@ -23,7 +26,7 @@ export class ToastContainerDirective{
         ...defaultToastConfig,
         ...config
       } 
-      const toastComponent = this.viewContainerRef.createComponent(toastComponentFactory)
+      const toastComponent = this.viewContainerRef.createComponent(this.toastComponentFactory)
       if(typeof message === 'string')
         toastComponent.instance.message = message
       if(message instanceof TemplateRef){
@@ -44,31 +47,41 @@ export class ToastContainerDirective{
       return dismissToast
     }
 
+    this.toastService.getToastHandler = () => {
+      return this.getToastHandler()
+    }
+
     this.apiService.interactiveViewer.uiHandle.getToastHandler = () => {
-      const handler = new ToastHandler()
-      let toastComponent:ComponentRef<ToastComponent>
-      handler.show = () => {
-        toastComponent = this.viewContainerRef.createComponent(toastComponentFactory)
-
-        toastComponent.instance.dismissable = handler.dismissable
-        toastComponent.instance.message = handler.message
-        toastComponent.instance.htmlMessage = handler.htmlMessage
-        toastComponent.instance.timeout = handler.timeout
-
-        const _subscription = toastComponent.instance.dismissed.subscribe(userInitiated => {
-          _subscription.unsubscribe()
-          handler.hide()
-        })
-      }
+      return this.getToastHandler()
+    }
+  }
 
-      handler.hide = () => {
-        if(toastComponent){
-          toastComponent.destroy()
-          toastComponent = null
-        }
-      }
+  public getToastHandler(){
+    const handler = new ToastHandler()
+    let toastComponent:ComponentRef<ToastComponent>
+    handler.show = () => {
+      toastComponent = this.viewContainerRef.createComponent(this.toastComponentFactory)
 
-      return handler
+      toastComponent.instance.dismissable = handler.dismissable
+
+      if (typeof handler.message === 'string') toastComponent.instance.message = handler.message
+      if (handler.message instanceof TemplateRef) toastComponent.instance.messageContainer.createEmbeddedView(handler.message as TemplateRef<any>)
+      toastComponent.instance.htmlMessage = handler.htmlMessage
+      toastComponent.instance.timeout = handler.timeout
+
+      const _subscription = toastComponent.instance.dismissed.subscribe(userInitiated => {
+        _subscription.unsubscribe()
+        handler.hide()
+      })
     }
+
+    handler.hide = () => {
+      if(toastComponent){
+        toastComponent.destroy()
+        toastComponent = null
+      }
+    }
+
+    return handler
   }
-}
\ No newline at end of file
+}
diff --git a/src/util/pipes/templateParcellationDecoration.pipe.ts b/src/util/pipes/templateParcellationDecoration.pipe.ts
new file mode 100644
index 0000000000000000000000000000000000000000..cb199ed5bfeeb46645bcc23b7140177b87e05729
--- /dev/null
+++ b/src/util/pipes/templateParcellationDecoration.pipe.ts
@@ -0,0 +1,48 @@
+import { Pipe, PipeTransform } from "@angular/core";
+
+const notNullNotEmptyString = (string) => !!string && string !== ''
+const notEmptyArray = (arr) => !!arr && arr instanceof Array && arr.length > 0
+
+/**
+ * extraButtons are needed to render (i) btn in dropdown menu
+ * this pipe should append the extraButtons property according to:
+ * - originalDatasets is defined
+ * - description is defined on either root level or properties level
+ */
+
+@Pipe({
+  name: 'templateParcellationsDecorationPipe'
+})
+
+export class TemplateParcellationsDecorationPipe implements PipeTransform{
+  public transform(parcellations:any[]){
+    return parcellations.map(p => {
+      const { description, properties = {}, publications } = p
+      const { description:pDescriptions, publications: pPublications } = properties
+      const defaultOriginaldataset = notNullNotEmptyString(description)
+        || notNullNotEmptyString(pDescriptions)
+        || notEmptyArray(publications)
+        || notEmptyArray(pPublications)
+          ? [{}]
+          : []
+
+      const { originDatasets = defaultOriginaldataset } = p
+      return {
+        ...p,
+        extraButtons: originDatasets
+          .map(({ kgSchema, kgId }) => {
+            return {
+              name: getNameFromSchemaId({ kgSchema, kgId }),
+              faIcon: 'fas fa-info-circle'
+            }
+          })
+      }
+    })
+  }
+}
+
+export const getNameFromSchemaId = ({ kgSchema=null, kgId=null } = {}) => JSON.stringify({kgSchema, kgId})
+export const getSchemaIdFromName = (string = '{}') => {
+  const {kgSchema=null, kgId=null} = JSON.parse(string)
+  return { kgSchema, kgId }
+}
\ No newline at end of file
diff --git a/src/util/pluginHandlerClasses/toastHandler.ts b/src/util/pluginHandlerClasses/toastHandler.ts
index 80d696980b907641d384600bcfe3643163037fe8..ed468840fa13ed4c09a73fcffe05ae14f50144db 100644
--- a/src/util/pluginHandlerClasses/toastHandler.ts
+++ b/src/util/pluginHandlerClasses/toastHandler.ts
@@ -1,5 +1,7 @@
+import { TemplateRef } from "@angular/core";
+
 export class ToastHandler{
-  message : string = 'handler.body'
+  message : string | TemplateRef<any> = 'handler.body'
   timeout : number = 3000
   dismissable : boolean = true
   show : () => void