diff --git a/__tests__/src/extend/pluginStore.test.js b/__tests__/src/extend/pluginStore.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..7afea0b72bfd10b73ad6e403622c418b6becfaee
--- /dev/null
+++ b/__tests__/src/extend/pluginStore.test.js
@@ -0,0 +1,78 @@
+import { pluginStore } from '../../../src/extend';
+
+describe('storePlugins()', () => {
+  it('should run without throw error when Array is passed', () => {
+    expect(() => pluginStore.storePlugins([])).not.toThrow();
+  });
+  it('should run without throw error when nothing is passed', () => {
+    expect(() => pluginStore.storePlugins()).not.toThrow();
+  });
+});
+
+describe('getPlugins', () => {
+  it('with no plugins should return undefined', () => {
+    pluginStore.storePlugins();
+    expect(pluginStore.getPlugins('target')).not.toBeDefined();
+  });
+  it('returns { mode -> plugin } mapping for target', () => {
+    const plugins = [
+      { target: 'Window', mode: 'delete' },
+      { target: 'Window', mode: 'delete' },
+      { target: 'Window', mode: 'replace' },
+      { target: 'Window', mode: 'replace' },
+      { target: 'Window', mode: 'wrap' },
+      { target: 'Window', mode: 'wrap' },
+      { target: 'Window', mode: 'add' },
+      { target: 'Window', mode: 'add' },
+
+      { target: 'TopBar', mode: 'delete' },
+      { target: 'TopBar', mode: 'delete' },
+      { target: 'TopBar', mode: 'replace' },
+      { target: 'TopBar', mode: 'replace' },
+      { target: 'TopBar', mode: 'wrap' },
+      { target: 'TopBar', mode: 'wrap' },
+      { target: 'TopBar', mode: 'add' },
+      { target: 'TopBar', mode: 'add' },
+    ];
+
+    pluginStore.storePlugins(plugins);
+
+    expect(pluginStore.getPlugins('Window')).toEqual({
+      delete: [
+        { target: 'Window', mode: 'delete' },
+        { target: 'Window', mode: 'delete' },
+      ],
+      replace: [
+        { target: 'Window', mode: 'replace' },
+        { target: 'Window', mode: 'replace' },
+      ],
+      wrap: [
+        { target: 'Window', mode: 'wrap' },
+        { target: 'Window', mode: 'wrap' },
+      ],
+      add: [
+        { target: 'Window', mode: 'add' },
+        { target: 'Window', mode: 'add' },
+      ],
+    });
+
+    expect(pluginStore.getPlugins('TopBar')).toEqual({
+      delete: [
+        { target: 'TopBar', mode: 'delete' },
+        { target: 'TopBar', mode: 'delete' },
+      ],
+      replace: [
+        { target: 'TopBar', mode: 'replace' },
+        { target: 'TopBar', mode: 'replace' },
+      ],
+      wrap: [
+        { target: 'TopBar', mode: 'wrap' },
+        { target: 'TopBar', mode: 'wrap' },
+      ],
+      add: [
+        { target: 'TopBar', mode: 'add' },
+        { target: 'TopBar', mode: 'add' },
+      ],
+    });
+  });
+});
diff --git a/__tests__/src/extend/withPlugins.test.js b/__tests__/src/extend/withPlugins.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..11509feddcd8085cab05d64176227b4307da5001
--- /dev/null
+++ b/__tests__/src/extend/withPlugins.test.js
@@ -0,0 +1,164 @@
+import React from 'react';
+import { shallow } from 'enzyme';
+import { withPlugins } from '../../../src/extend';
+import { pluginStore } from '../../../src/extend/pluginStore';
+
+
+jest.mock('../../../src/extend/pluginStore');
+
+/** */
+const Target = props => <div>Hello</div>;
+
+/** create wrapper  */
+function createPluginHoc(plugins) {
+  pluginStore.getPlugins = () => plugins;
+  const props = { foo: 1, bar: 2 };
+  const PluginHoc = withPlugins('Target', Target);
+  return shallow(<PluginHoc {...props} />);
+}
+
+describe('withPlugins', () => {
+  it('should return a function (normal function call)', () => {
+    expect(withPlugins('Target', Target)).toBeInstanceOf(Function);
+  });
+
+  it('should return a function (curry function call)', () => {
+    expect(withPlugins('Target')(Target)).toBeInstanceOf(Function);
+  });
+
+  it('displayName prop of returned function is based on target name argument', () => {
+    expect(withPlugins('Bubu', Target).displayName)
+      .toBe('WithPlugins(Bubu)');
+  });
+});
+
+describe('PluginHoc: if no plugin exists for the target', () => {
+  it('renders the target component', () => {
+    const hoc = createPluginHoc([]);
+    expect(hoc.find(Target).length).toBe(1);
+    expect(hoc.find(Target).props().foo).toBe(1);
+    expect(hoc.find(Target).props().bar).toBe(2);
+  });
+});
+
+describe('PluginHoc: if a delete-plugin exists for the target', () => {
+  it('renders nothing', () => {
+    const plugins = {
+      delete: [
+        { target: 'Target', mode: 'delete' },
+      ],
+      replace: [
+        { target: 'Target', mode: 'replace' },
+      ],
+      wrap: [
+        { target: 'Target', mode: 'wrap' },
+      ],
+      add: [
+        { target: 'Target', mode: 'add' },
+      ],
+    };
+
+    const hoc = createPluginHoc(plugins);
+    expect(hoc.find('*').length).toBe(0);
+  });
+});
+
+describe('PluginHoc: if replace-plugins exists but no delete-plugin', () => {
+  it('renders the first replace-plugin component', () => {
+    /** */ const ReplacePluginComponentA = props => <div>look i am a plugin</div>;
+    /** */ const ReplacePluginComponentB = props => <div>look i am a plugin</div>;
+    /** */ const WrapPluginComponent = props => <div>look i am a plugin</div>;
+    /** */ const AddPluginComponent = props => <div>look i am a plugin</div>;
+    const plugins = {
+      replace: [
+        { target: 'Target', mode: 'replace', component: ReplacePluginComponentA },
+        { target: 'Target', mode: 'replace', component: ReplacePluginComponentB },
+      ],
+      wrap: [
+        { target: 'Target', mode: 'wrap', component: WrapPluginComponent },
+      ],
+      add: [
+        { target: 'Target', mode: 'add', component: AddPluginComponent },
+      ],
+    };
+    const hoc = createPluginHoc(plugins);
+    const selector = 'Connect(ReplacePluginComponentA)';
+    expect(hoc.find(selector).length).toBe(1);
+    expect(hoc.find(selector).props().foo).toBe(1);
+    expect(hoc.find(selector).props().bar).toBe(2);
+  });
+});
+
+describe('PluginHoc: if wrap-plugins exists but no delete-plugin, no replace-plugin and no add-plugins', () => {
+  it('renders the first wrap-plugin and passes the target component as prop', () => {
+    /** */ const WrapPluginComponentA = props => <div>look i am a plugin</div>;
+    /** */ const WrapPluginComponentB = props => <div>look i am a plugin</div>;
+    const plugins = {
+      wrap: [
+        { target: 'Target', mode: 'wrap', component: WrapPluginComponentA },
+        { target: 'Target', mode: 'wrap', component: WrapPluginComponentB },
+      ],
+    };
+    const hoc = createPluginHoc(plugins);
+    const selector = 'Connect(WrapPluginComponentA)';
+    expect(hoc.find(selector).length).toBe(1);
+    expect(hoc.find(selector).props().foo).toBe(1);
+    expect(hoc.find(selector).props().bar).toBe(2);
+    expect(hoc.find(selector).props().TargetComponent).toBe(Target);
+  });
+});
+
+describe('PluginHoc: if add-plugins exist but no delete-plugin, no replace-plugin and no wrap-plugin', () => {
+  it('renders the target component and passes all add-plugin components as a prop', () => {
+    /** */ const AddPluginComponentA = props => <div>look i am a plugin</div>;
+    /** */ const AddPluginComponentB = props => <div>look i am a plugin</div>;
+    const plugins = {
+      add: [
+        { target: 'Target', mode: 'add', component: AddPluginComponentA },
+        { target: 'Target', mode: 'add', component: AddPluginComponentB },
+      ],
+    };
+    const hoc = createPluginHoc(plugins);
+    const selector = Target;
+    expect(hoc.find(selector).length).toBe(1);
+    expect(hoc.find(selector).props().foo).toBe(1);
+    expect(hoc.find(selector).props().bar).toBe(2);
+    expect(hoc.find(selector).props().PluginComponents[0].displayName)
+      .toBe('Connect(AddPluginComponentA)');
+    expect(hoc.find(selector).props().PluginComponents[1].displayName)
+      .toBe('Connect(AddPluginComponentB)');
+  });
+});
+
+describe('PluginHoc: if add-plugins AND wrap-plugins exist but no delete-plugin and no replace-plugin', () => {
+  it('passes all add-plugin components to target component and renders the first wrap-plugin with the target component as prop', () => {
+    /** */ const WrapPluginComponentA = props => <div>look i am a plugin</div>;
+    /** */ const WrapPluginComponentB = props => <div>look i am a plugin</div>;
+    /** */ const AddPluginComponentA = props => <div>look i am a plugin</div>;
+    /** */ const AddPluginComponentB = props => <div>look i am a plugin</div>;
+    const plugins = {
+      add: [
+        { target: 'Target', mode: 'add', component: AddPluginComponentA },
+        { target: 'Target', mode: 'add', component: AddPluginComponentB },
+      ],
+      wrap: [
+        { target: 'Target', mode: 'wrap', component: WrapPluginComponentA },
+        { target: 'Target', mode: 'wrap', component: WrapPluginComponentB },
+      ],
+    };
+    const hoc = createPluginHoc(plugins);
+    const selector = 'Connect(WrapPluginComponentA)';
+    expect(hoc.find(selector).length).toBe(1);
+    expect(hoc.find(selector).props().foo).toBe(1);
+    expect(hoc.find(selector).props().bar).toBe(2);
+
+    const { TargetComponent } = hoc.find(selector).props();
+    const target = shallow(<TargetComponent bubu={10} kiki={20} />);
+    expect(target.props().bubu).toBe(10);
+    expect(target.props().kiki).toBe(20);
+    expect(target.props().PluginComponents[0].displayName)
+      .toBe('Connect(AddPluginComponentA)');
+    expect(target.props().PluginComponents[1].displayName)
+      .toBe('Connect(AddPluginComponentB)');
+  });
+});
diff --git a/src/components/WorkspaceControlPanelButtons.js b/src/components/WorkspaceControlPanelButtons.js
index 3e23a20ed925aaffffc2018c3fd21922993e791e..b4150e929e2316cab7eb3ce5f10483547b24b4ec 100644
--- a/src/components/WorkspaceControlPanelButtons.js
+++ b/src/components/WorkspaceControlPanelButtons.js
@@ -5,8 +5,13 @@ import WorkspaceMenuButton from '../containers/WorkspaceMenuButton';
 
 /** Renders plugins */
 const PluginHook = (props) => {
-  const { PluginComponent } = props; // eslint-disable-line react/prop-types
-  return PluginComponent ? <PluginComponent {...props} /> : null;
+  const { PluginComponents } = props; // eslint-disable-line react/prop-types
+  if (PluginComponents) {
+    return PluginComponents.map((PluginComponent, index) => (
+      <PluginComponent {...props} key={index} /> // eslint-disable-line react/no-array-index-key
+    ));
+  }
+  return null;
 };
 
 /**
diff --git a/src/extend/pluginStore.js b/src/extend/pluginStore.js
index 0aee6f1cf66c71463feae63f3b10ddb3d558b37c..a95b8c91c5e9c4da8240536eba2047b2562881b9 100644
--- a/src/extend/pluginStore.js
+++ b/src/extend/pluginStore.js
@@ -1,10 +1,56 @@
+import update from 'lodash/update';
+
 export const pluginStore = {
-  /** */
-  getPlugins() {
-    return this.plugins || [];
+  /**
+  * Get plugins for target
+  *
+  * @param {String} targetName
+  * @return {Object | undefined } - looks like:
+  *
+  *  {
+  *    delete:   [plugin1, ...],
+  *    replace:  [plugin2, ...],
+  *    wrap:     [plugin3, ...],
+  *    add:      [plugin4, ...],
+  *  }
+  */
+  getPlugins(target) {
+    return this.pluginMap[target];
   },
-  /** */
+  /**
+   * Store Plugins
+   *
+   * @param {Array} plugins
+   */
   storePlugins(plugins) {
-    this.plugins = plugins || [];
+    this.pluginMap = mapPlugins(plugins || []);
   },
 };
+
+/**
+ * Returns a mapping from plugins to targets and modes
+ *
+ * @param {Array} plugins
+ * @return {Object} - looks like:
+ *
+ *
+ *  {
+ *    'WorkspacePanel': {
+ *      delete:   [plugin1, ...],
+ *      replace:  [plugin2, ...],
+ *      wrap:     [plugin3, ...],
+ *      add:      [plugin4, ...],
+ *    },
+ *    'Window': {
+ *      delete:   [plugin1, ...],
+ *      replace:  [plugin2, ...],
+ *      wrap:     [plugin3, ...],
+ *      add:      [plugin4, ...],
+ *    }
+ *  }
+ */
+function mapPlugins(plugins) {
+  return plugins.reduce((map, plugin) => (
+    update(map, [plugin.target, plugin.mode], x => [...x || [], plugin])
+  ), {});
+}
diff --git a/src/extend/withPlugins.js b/src/extend/withPlugins.js
index 681eca0a8d65ce719e5b1529ea81ede3578d953e..7cd175c067d9252e7e73198d3d5f9e22d677f2da 100644
--- a/src/extend/withPlugins.js
+++ b/src/extend/withPlugins.js
@@ -1,5 +1,6 @@
 import React, { Component } from 'react';
 import curry from 'lodash/curry';
+import isEmpty from 'lodash/isEmpty';
 import { connect } from 'react-redux';
 import { pluginStore } from '.';
 
@@ -8,25 +9,44 @@ function _withPlugins(targetName, TargetComponent) { // eslint-disable-line no-u
   /** plugin wrapper hoc */
   class PluginHoc extends Component {
     /** render */
-    render() {
-      const plugin = pluginStore.getPlugins().find(p => p.target === targetName);
+    render() { // eslint-disable-line consistent-return
+      const plugins = pluginStore.getPlugins(targetName);
 
-      if (plugin && plugin.mode === 'delete') {
+      if (isEmpty(plugins)) {
+        return <TargetComponent {...this.props} />;
+      }
+
+      if (!isEmpty(plugins.delete)) {
         return null;
       }
-      if (plugin && plugin.mode === 'replace') {
-        const PluginComponent = connectPluginComponent(plugin);
-        return <PluginComponent {...this.props} />;
+
+      if (!isEmpty(plugins.replace)) {
+        const ReplacePluginComponent = connectPluginComponent(plugins.replace[0]);
+        return <ReplacePluginComponent {...this.props} />;
       }
-      if (plugin && plugin.mode === 'add') {
-        const PluginComponent = connectPluginComponent(plugin);
-        return <TargetComponent {...this.props} PluginComponent={PluginComponent} />;
+
+      if (!isEmpty(plugins.wrap) && !isEmpty(plugins.add)) {
+        const AddPluginComponents = plugins.add.map(plugin => connectPluginComponent(plugin));
+        /** we want to pass an react constructor to WrapPluginComponent
+            rather then a react element */
+        const TargetComponentWithAddPlugins = props => (
+          <TargetComponent {...props} PluginComponents={AddPluginComponents} />
+        );
+        const WrapPluginComponent = connectPluginComponent(plugins.wrap[0]);
+        return (
+          <WrapPluginComponent {...this.props} TargetComponent={TargetComponentWithAddPlugins} />
+        );
       }
-      if (plugin && plugin.mode === 'wrap') {
-        const PluginComponent = connectPluginComponent(plugin);
-        return <PluginComponent {...this.props} TargetComponent={TargetComponent} />;
+
+      if (!isEmpty(plugins.wrap)) {
+        const WrapPluginComponent = connectPluginComponent(plugins.wrap[0]);
+        return <WrapPluginComponent {...this.props} TargetComponent={TargetComponent} />;
+      }
+
+      if (!isEmpty(plugins.add)) {
+        const AddPluginComponents = plugins.add.map(plugin => connectPluginComponent(plugin));
+        return <TargetComponent {...this.props} PluginComponents={AddPluginComponents} />;
       }
-      return <TargetComponent {...this.props} />;
     }
   }