diff --git a/src/App.js b/src/App.js
index 676465d36b760623aa6d05f08ea1b7ce948c82c4..49ef483d5f200c0da5f6d8074d21606aa8ac7c59 100644
--- a/src/App.js
+++ b/src/App.js
@@ -4,6 +4,7 @@ import { HashRouter, Switch, Route } from 'react-router-dom';
 
 import EntryPage from './components/entry-page/entry-page.js';
 import ErrorDialog from './components/dialog/error-dialog.js';
+import ToastNotification from './components/dialog/toast-notification.js';
 import ExperimentOverview from './components/experiment-overview/experiment-overview.js';
 
 class App extends React.Component {
@@ -11,6 +12,7 @@ class App extends React.Component {
     return(
       <div>
         <ErrorDialog />
+        <ToastNotification/>
         <HashRouter>
           <Switch>
             <Route path='/experiments-overview'>
diff --git a/src/components/dialog/error-dialog.css b/src/components/dialog/error-dialog.css
index 02e9b3a1eae2d741aa5f835cdf59ecc137e57c69..b9f8a930181469c9e82ecdb54385ec6ffa5e6f8e 100644
--- a/src/components/dialog/error-dialog.css
+++ b/src/components/dialog/error-dialog.css
@@ -1,4 +1,4 @@
-.modal-dialog-wrapper {
+.error-dialog-wrapper {
   position: fixed;
   width: 100%;
   height: 100%;
diff --git a/src/components/dialog/error-dialog.js b/src/components/dialog/error-dialog.js
index 67746983eafb8e1ea2d304d4ec6f73e3ff134ee0..d5a68975d105628967957365ce0e946ebb7c0c5a 100644
--- a/src/components/dialog/error-dialog.js
+++ b/src/components/dialog/error-dialog.js
@@ -1,7 +1,7 @@
 import React from 'react';
 import { Modal, Button } from 'react-bootstrap';
 
-import ErrorHandlerService from '../../services/error-handler-service.js';
+import DialogService from '../../services/dialog-service.js';
 
 import './error-dialog.css';
 
@@ -15,10 +15,11 @@ class ErrorDialog extends React.Component{
   }
 
   async componentDidMount() {
-    ErrorHandlerService.instance.addListener(
-      ErrorHandlerService.EVENTS.ERROR, (error) => {
+    DialogService.instance.addListener(
+      DialogService.EVENTS.ERROR, (error) => {
         this.onError(error);
-      });
+      }
+    );
   }
 
   onError(error) {
@@ -45,7 +46,7 @@ class ErrorDialog extends React.Component{
     return (
       <div>
         {error?
-          <div className="modal-dialog-wrapper">
+          <div className="error-dialog-wrapper">
             <Modal.Dialog>
               <Modal.Header className="modal-header">
                 <h4>{error.type}</h4>
diff --git a/src/components/dialog/toast-notification.js b/src/components/dialog/toast-notification.js
new file mode 100644
index 0000000000000000000000000000000000000000..564b1379f888342bfc2e2fe62ebb1b360e2e5ac9
--- /dev/null
+++ b/src/components/dialog/toast-notification.js
@@ -0,0 +1,60 @@
+import { Toast } from 'bootstrap';
+import React from 'react'
+
+import DialogService from '../../services/dialog-service.js'
+
+class NotificationDialog extends React.Component{
+  constructor(props){
+    super(props);
+    this.state = {
+      notifications: [],
+    };
+  }
+
+  async componentDidMount() {
+    DialogService.instance.addListener(
+      DialogService.EVENTS.NOTIFICATION, (notification) => {
+        this.onNotification(notification);
+      }
+    );
+  }
+
+  onNotification(notification) {
+    this.setState({
+      notifications: this.state.notifications.append(notification)
+    });
+  }
+
+  onClose(index) {
+    this.setState({
+      notifications: notifications.splice(index, 1)
+    });
+  }
+
+  render(){
+    return(
+        <div>
+          {this.state.notifications?
+            <ol>
+              {this.state.notifications.map(notification => {
+                return (
+                  <div className="toast-dialog-wrapper">
+                    <Toast.Dialog onClose={this.onClose(index)}>
+                      <Toast.Header>
+                        <h4>{notification.type}</h4>
+                      </Toast.Header>
+                      <Toast.Body>
+                        {notification.message}
+                      </Toast.Body>
+                    </Toast.Dialog>
+                  </div>
+                  );
+                })
+              }
+            </ol>
+            : null
+          }
+        </div>
+    )
+  }
+}
\ No newline at end of file
diff --git a/src/services/error-handler-service.js b/src/services/dialog-service.js
similarity index 54%
rename from src/services/error-handler-service.js
rename to src/services/dialog-service.js
index 026e9396a03fe5f02f74bab0cd252721fba8104c..9a0f6b968480d45f6ca3d9470e27f33bcb8b51be 100644
--- a/src/services/error-handler-service.js
+++ b/src/services/dialog-service.js
@@ -12,7 +12,7 @@ const SINGLETON_ENFORCER = Symbol();
  *  - data: related content | optional
  *  - stack: call stack | optional
  */
-class ErrorHandlerService extends EventEmitter {
+class DialogService extends EventEmitter {
   constructor(enforcer) {
     super();
     if (enforcer !== SINGLETON_ENFORCER) {
@@ -22,7 +22,7 @@ class ErrorHandlerService extends EventEmitter {
 
   static get instance() {
     if (_instance == null) {
-      _instance = new ErrorHandlerService(SINGLETON_ENFORCER);
+      _instance = new DialogService(SINGLETON_ENFORCER);
     }
 
     return _instance;
@@ -31,28 +31,38 @@ class ErrorHandlerService extends EventEmitter {
   // HTTP request error
   networkError(error) {
     error.type = 'Network Error';
-    this.emit(ErrorHandlerService.EVENTS.ERROR, error);
+    this.emit(DialogService.EVENTS.ERROR, error);
   }
 
   // Handling data error
   dataError(error){
     error.type = 'Data Error';
-    this.emit(ErrorHandlerService.EVENTS.ERROR, error);
+    this.emit(DialogService.EVENTS.ERROR, error);
   }
 
-  startSimulationError(error) {
-    error.type = 'Start Simulation Error';
-    this.emit(ErrorHandlerService.EVENTS.ERROR, error);
+  simulationError(error) {
+    error.type = 'Simulation Error';
+    this.emit(DialogService.EVENTS.ERROR, error);
   }
 
-  updateSimulationError(error) {
-    error.type = 'Update Simulation Error';
-    this.emit(ErrorHandlerService.EVENTS.ERROR, error);
+  progressNotification(notification) {
+    notification.type = 'Progress Status';
+    this.emit(DialogService.EVENTS.NOTIFICATION, notification)
   }
+
+  warningNotification(notification) {
+    notification.type = 'Warning'
+    this.emit(DialogService.EVENTS.NOTIFICATION, notification)
+  }
+  
 }
 
-ErrorHandlerService.EVENTS = Object.freeze({
+DialogService.EVENTS = Object.freeze({
   ERROR: 'ERROR'
 });
 
-export default ErrorHandlerService;
\ No newline at end of file
+DialogService.EVENTS = Object.freeze({
+  NOTIFICATION: 'NOTIFICATION'
+})
+
+export default DialogService;
\ No newline at end of file
diff --git a/src/services/experiments/execution/__tests__/running-simulation-service.test.js b/src/services/experiments/execution/__tests__/running-simulation-service.test.js
index 7af3b6e72eb1dbc0f5b53d53d0a9ffd960e99855..095c81384082acdce11f07dd4b2548a98d6ede46 100644
--- a/src/services/experiments/execution/__tests__/running-simulation-service.test.js
+++ b/src/services/experiments/execution/__tests__/running-simulation-service.test.js
@@ -8,7 +8,7 @@ import MockAvailableServers from '../../../../mocks/mock_available-servers.json'
 import MockSimulations from '../../../../mocks/mock_simulations.json';
 
 import RunningSimulationService from '../running-simulation-service.js';
-import ErrorHandlerService from '../../../error-handler-service';
+import DialogService from '../../../error-handler-service';
 import RoslibService from '../../../roslib-service';
 import { EXPERIMENT_STATE } from '../../experiment-constants.js';
 
@@ -41,11 +41,11 @@ test('initializes and gets the simulation resources', async () => {
   expect(resources).toBeDefined();
 
   // failure case
-  jest.spyOn(ErrorHandlerService.instance, 'networkError').mockImplementation(() => { });
+  jest.spyOn(DialogService.instance, 'networkError').mockImplementation(() => { });
   let simIDFailure = 0;
-  expect(ErrorHandlerService.instance.networkError).not.toHaveBeenCalled();
+  expect(DialogService.instance.networkError).not.toHaveBeenCalled();
   resources = await RunningSimulationService.instance.initConfigFiles(serverBaseURL, simIDFailure);
-  expect(ErrorHandlerService.instance.networkError).toHaveBeenCalled();
+  expect(DialogService.instance.networkError).toHaveBeenCalled();
 });
 
 test('verifies whether a simulation is ready', async () => {
@@ -139,7 +139,7 @@ test('register for ROS status information', () => {
 
 test('can retrieve the state of a simulation', async () => {
   let returnValueGET = undefined;
-  jest.spyOn(ErrorHandlerService.instance, 'networkError').mockImplementation();
+  jest.spyOn(DialogService.instance, 'networkError').mockImplementation();
   jest.spyOn(RunningSimulationService.instance, 'httpRequestGET').mockImplementation(() => {
     if (RunningSimulationService.instance.httpRequestGET.mock.calls.length === 1) {
       returnValueGET = { state: EXPERIMENT_STATE.PAUSED }; // proper state msg
@@ -161,12 +161,12 @@ test('can retrieve the state of a simulation', async () => {
 
   // call 2 => rejected
   simSate = await RunningSimulationService.instance.getState('test-url', 1);
-  expect(ErrorHandlerService.instance.networkError).toHaveBeenCalled();
+  expect(DialogService.instance.networkError).toHaveBeenCalled();
 });
 
 test('can set the state of a simulation', async () => {
   let returnValuePUT = undefined;
-  jest.spyOn(ErrorHandlerService.instance, 'updateSimulationError').mockImplementation();
+  jest.spyOn(DialogService.instance, 'simulationError').mockImplementation();
   jest.spyOn(RunningSimulationService.instance, 'httpRequestPUT').mockImplementation(() => {
     if (RunningSimulationService.instance.httpRequestGET.mock.calls.length === 1) {
       returnValuePUT = {};
@@ -184,5 +184,5 @@ test('can set the state of a simulation', async () => {
 
   // call 2 => rejected
   returnValue = await RunningSimulationService.instance.updateState('test-url', 1, EXPERIMENT_STATE.PAUSED);
-  expect(ErrorHandlerService.instance.updateSimulationError).toHaveBeenCalled();
+  expect(DialogService.instance.simulationError).toHaveBeenCalled();
 });
\ No newline at end of file
diff --git a/src/services/experiments/execution/__tests__/server-resources-service.test.js b/src/services/experiments/execution/__tests__/server-resources-service.test.js
index 92ecf5b8b0ccf30ff1e1155aec4540ef8791a484..6726f3f9f2f21fc0aa5f7b3dbaa0b4ecd9203fb9 100644
--- a/src/services/experiments/execution/__tests__/server-resources-service.test.js
+++ b/src/services/experiments/execution/__tests__/server-resources-service.test.js
@@ -7,7 +7,7 @@ import 'jest-fetch-mock';
 import MockServerconfig from '../../../../mocks/mock_server-config.json';
 
 import ServerResourcesService from '../../../../services/experiments/execution/server-resources-service';
-import ErrorHandlerService from '../../../error-handler-service';
+import DialogService from '../../../error-handler-service';
 
 jest.setTimeout(10000);
 
@@ -67,9 +67,9 @@ test('can get a server config', async () => {
   jest.spyOn(ServerResourcesService.instance, 'httpRequestGET').mockImplementation(() => {
     return Promise.reject();
   });
-  jest.spyOn(ErrorHandlerService.instance, 'networkError').mockImplementation();
+  jest.spyOn(DialogService.instance, 'networkError').mockImplementation();
   config = await ServerResourcesService.instance.getServerConfig('test-server-id');
-  expect(ErrorHandlerService.instance.networkError).toHaveBeenCalled();
+  expect(DialogService.instance.networkError).toHaveBeenCalled();
 });
 
 test('should stop polling updates when window is unloaded', async () => {
diff --git a/src/services/experiments/execution/experiment-execution-service.js b/src/services/experiments/execution/experiment-execution-service.js
index 0076fbf602d0a6d4ab7e959881ac7265aee4fa31..bcadae7e3f1088ed76f0453cc62b1d9622c52ff5 100644
--- a/src/services/experiments/execution/experiment-execution-service.js
+++ b/src/services/experiments/execution/experiment-execution-service.js
@@ -3,7 +3,7 @@ import _ from 'lodash';
 //import NrpAnalyticsService from '../../nrp-analytics-service.js';
 import ServerResourcesService from './server-resources-service.js';
 import SimulationService from './running-simulation-service.js';
-import ErrorHandlerService from '../../error-handler-service';
+import DialogService from '../../dialog-service';
 import { HttpService } from '../../http-service.js';
 import { EXPERIMENT_STATE } from '../experiment-constants.js';
 
@@ -61,8 +61,8 @@ class ExperimentExecutionService extends HttpService {
     let brainProcesses = launchSingleMode ? 1 : experiment.configuration.brainProcesses;
 
     //TODO: placeholder, register actual progress callback later
-    let progressCallback = (msg) => {
-      console.info(msg);
+    let progressCallback = (notification) => {
+      DialogService.instance.progressNotification(notification);
     };
 
     let launchOnNextServer = async () => {
@@ -90,7 +90,7 @@ class ExperimentExecutionService extends HttpService {
         progressCallback
       ).catch((failure) => {
         if (failure.error) {
-          ErrorHandlerService.instance.startSimulationError(failure.error);
+          DialogService.instance.simulationError(failure.error);
         }
         fatalErrorOccurred = fatalErrorOccurred || failure.isFatal;
 
diff --git a/src/services/experiments/execution/running-simulation-service.js b/src/services/experiments/execution/running-simulation-service.js
index 754ccc8d96d54ab3e014630e03654ce5905ea010..2ef55859c3ec42302871b772c9d3c58a5641e68c 100644
--- a/src/services/experiments/execution/running-simulation-service.js
+++ b/src/services/experiments/execution/running-simulation-service.js
@@ -1,4 +1,4 @@
-import ErrorHandlerService from '../../error-handler-service.js';
+import DialogService from '../../dialog-service.js';
 import RoslibService from '../../roslib-service.js';
 import { HttpService } from '../../http-service.js';
 import { EXPERIMENT_STATE } from '../experiment-constants.js';
@@ -44,7 +44,7 @@ class SimulationService extends HttpService {
       cachedConfigFiles = response.resources;
     }
     catch (error) {
-      ErrorHandlerService.instance.networkError(error);
+      DialogService.instance.networkError(error);
     }
 
     return cachedConfigFiles;
@@ -151,7 +151,7 @@ class SimulationService extends HttpService {
       return response;
     }
     catch (error) {
-      ErrorHandlerService.instance.networkError(error);
+      DialogService.instance.networkError(error);
     }
   }
 
@@ -168,7 +168,7 @@ class SimulationService extends HttpService {
       return response;
     }
     catch (error) {
-      ErrorHandlerService.instance.updateSimulationError(error);
+      DialogService.instance.simulationError(error);
     }
   }
 }
diff --git a/src/services/experiments/execution/server-resources-service.js b/src/services/experiments/execution/server-resources-service.js
index 8a2eb78c48f3f299c872187fbd239b18279c2003..8499b472a8619e251ef7769cfb28561b6704809e 100644
--- a/src/services/experiments/execution/server-resources-service.js
+++ b/src/services/experiments/execution/server-resources-service.js
@@ -1,4 +1,4 @@
-import ErrorHandlerService from '../../error-handler-service.js';
+import DialogService from '../../dialog-service.js';
 import { HttpService } from '../../http-service.js';
 
 import endpoints from '../../proxy/data/endpoints.json';
@@ -79,7 +79,7 @@ class ServerResourcesService extends HttpService {
       .then(async (response) => {
         return await response.json();
       })
-      .catch(ErrorHandlerService.instance.networkError);
+      .catch(DialogService.instance.networkError);
   }
 }
 
diff --git a/src/services/experiments/files/experiment-storage-service.js b/src/services/experiments/files/experiment-storage-service.js
index 0cf994dac08ab916701831c86cfe1e71e75fe1f8..8d6326388acea05cc17ed61d00daeb35c439b230 100644
--- a/src/services/experiments/files/experiment-storage-service.js
+++ b/src/services/experiments/files/experiment-storage-service.js
@@ -3,7 +3,7 @@ import { EXPERIMENT_RIGHTS } from '../experiment-constants';
 
 import endpoints from '../../proxy/data/endpoints.json';
 import config from '../../../config.json';
-import ErrorHandlerService from '../../error-handler-service.js';
+import DialogService from '../../dialog-service.js';
 
 const storageURL = `${config.api.proxy.url}${endpoints.proxy.storage.url}`;
 const storageExperimentsURL = `${config.api.proxy.url}${endpoints.proxy.storage.experiments.url}`;
@@ -79,7 +79,7 @@ class ExperimentStorageService extends HttpService {
         this.emit(ExperimentStorageService.EVENTS.UPDATE_EXPERIMENTS, this.experiments);
       }
       catch (error) {
-        ErrorHandlerService.instance.networkError(error);
+        DialogService.instance.networkError(error);
       }
     }
 
diff --git a/src/services/experiments/files/import-experiment-service.js b/src/services/experiments/files/import-experiment-service.js
index 45709388d357a983d7d0e58d343506a9d696aa00..5ae1b74db8e043de07d94bd2cad534237542ca8a 100644
--- a/src/services/experiments/files/import-experiment-service.js
+++ b/src/services/experiments/files/import-experiment-service.js
@@ -3,7 +3,7 @@ import JSZip from 'jszip';
 
 import endpoints from '../../proxy/data/endpoints.json';
 import config from '../../../config.json';
-import ErrorHandlerService from '../../error-handler-service.js';
+import DialogService from '../../dialog-service.js';
 const importExperimentURL = `${config.api.proxy.url}${endpoints.proxy.storage.importExperiment.url}`;
 const scanStorageURL = `${config.api.proxy.url}${endpoints.proxy.storage.scanStorage.url}`;
 
@@ -69,7 +69,7 @@ export default class ImportExperimentService extends HttpService {
   async scanStorage() {
     return this.httpRequestPOST(scanStorageURL)
       .then(response => this.getScanStorageResponse(response))
-      .catch(error => ErrorHandlerService.instance.networkError(error));
+      .catch(error => DialogService.instance.networkError(error));
   }
 
   async zipExperimentFolder(event) {
@@ -106,7 +106,7 @@ export default class ImportExperimentService extends HttpService {
             )
           )
           .catch(error => {
-            ErrorHandlerService.instance.dataError(error);
+            DialogService.instance.dataError(error);
             return Promise.reject(error);
           })
       );
@@ -115,7 +115,7 @@ export default class ImportExperimentService extends HttpService {
     return Promise.all(promises)
       .then(() => zip.generateAsync({ type: 'blob' }))
       .catch(error => {
-        ErrorHandlerService.instance.dataError(error);
+        DialogService.instance.dataError(error);
         return Promise.reject(error);
       });
   }
@@ -124,7 +124,7 @@ export default class ImportExperimentService extends HttpService {
     return this.zipExperimentFolder(event).then(async zipContent => {
       return this.httpRequestPOST(importExperimentURL, zipContent, options)
         .then(response => response.json())
-        .catch(error => ErrorHandlerService.instance.networkError(error)
+        .catch(error => DialogService.instance.networkError(error)
         );
     });
   }
@@ -151,7 +151,7 @@ export default class ImportExperimentService extends HttpService {
         zipContents.map(zipContent =>
           this.httpRequestPOST(importExperimentURL, zipContent, options)
             .catch(error => {
-              ErrorHandlerService.instance.networkError(error);
+              DialogService.instance.networkError(error);
               return Promise.reject(error);
             })
         )