diff --git a/__tests__/src/extend/pluginPreprocessing.test.js b/__tests__/src/extend/pluginPreprocessing.test.js
deleted file mode 100644
index d695c53c98d613841e2cec87fe46782c456ec079..0000000000000000000000000000000000000000
--- a/__tests__/src/extend/pluginPreprocessing.test.js
+++ /dev/null
@@ -1,146 +0,0 @@
-import {
-  filterValidPlugins,
-  connectPluginsToStore,
-  addPluginReducersToStore,
-  createTargetToPluginMapping,
-} from '../../../src/extend/pluginPreprocessing';
-
-
-describe('filterValidPlugins', () => {
-  it('returns empty array if plugin array is empty', () => {
-    expect(filterValidPlugins([])).toEqual([]);
-  });
-
-  it('returns only valid plugins', () => {
-    const plugins = [
-      {
-        component: props => null,
-        mode: 'add',
-        name: 'valid plugin 1',
-        target: 'Window',
-      },
-      {
-        component: props => null,
-        mode: 'wrap',
-        name: 'valid plugin 2',
-        target: 'Window',
-      },
-      {
-        name: 'invalid Plugin 1',
-      },
-      {
-        name: 'invalid Plugin 2',
-      },
-    ];
-    const result = filterValidPlugins(plugins);
-    expect(result.length).toBe(2);
-    expect(result[0].name).toBe('valid plugin 1');
-    expect(result[1].name).toBe('valid plugin 2');
-  });
-});
-
-describe('createTargetToPluginMapping', () => {
-  it('returns empty object if plugin array is empty', () => {
-    expect(createTargetToPluginMapping([])).toEqual({});
-  });
-
-  it('should create a mapping from targets to plugins and modes', () => {
-    /** */
-    const component = props => null;
-
-    const plugins = [
-      { component, mode: 'wrap', target: 'Window' },
-      { component, mode: 'wrap', target: 'Window' },
-      { component, mode: 'add', target: 'Window' },
-      { component, mode: 'add', target: 'Window' },
-
-      { component, mode: 'wrap', target: 'TopBar' },
-      { component, mode: 'wrap', target: 'TopBar' },
-      { component, mode: 'add', target: 'TopBar' },
-      { component, mode: 'add', target: 'TopBar' },
-    ];
-
-    expect(createTargetToPluginMapping(plugins)).toEqual({
-      TopBar: {
-        add: [
-          { component, mode: 'add', target: 'TopBar' },
-          { component, mode: 'add', target: 'TopBar' },
-        ],
-        wrap: [
-          { component, mode: 'wrap', target: 'TopBar' },
-          { component, mode: 'wrap', target: 'TopBar' },
-        ],
-      },
-      Window: {
-        add: [
-          { component, mode: 'add', target: 'Window' },
-          { component, mode: 'add', target: 'Window' },
-        ],
-        wrap: [
-          { component, mode: 'wrap', target: 'Window' },
-          { component, mode: 'wrap', target: 'Window' },
-        ],
-      },
-    });
-  });
-});
-
-describe('connectPluginsToStore', () => {
-  it('returns empty array if plugin array is empty', () => {
-    expect(filterValidPlugins([])).toEqual([]);
-  });
-
-  it('returns plugins with components connected to store', () => {
-    /** */
-    const ComponentA = props => null;
-    /** */
-    const ComponentB = props => null;
-
-    const plugins = [
-      { component: ComponentA, mode: 'wrap', target: 'Window' },
-      { component: ComponentB, mode: 'add', target: 'TopBar' },
-    ];
-
-    const result = connectPluginsToStore(plugins);
-    expect(result.length).toBe(2);
-    expect(result[0].component.displayName).toBe('Connect(ComponentA)');
-    expect(result[1].component.displayName).toBe('Connect(ComponentB)');
-  });
-});
-
-describe('addPluginReducersToStore', () => {
-  const store = { replaceReducer: jest.fn() };
-  const createRootReducer = jest.fn(pluginReducers => pluginReducers);
-
-  /** */ const fooReducer = x => x;
-  /** */ const barReducer = x => x;
-  /** */ const bazReducer = x => x;
-
-  const plugins = [
-    {
-      component: props => null,
-      mode: 'add',
-      reducers: {
-        bar: barReducer,
-        foo: fooReducer,
-      },
-      target: 'Window',
-    },
-    {
-      component: props => null,
-      mode: 'add',
-      reducers: {
-        baz: bazReducer,
-      },
-      target: 'Window',
-    },
-  ];
-
-  addPluginReducersToStore(store, createRootReducer, plugins);
-  expect(store.replaceReducer.mock.calls.length).toBe(1);
-  expect(store.replaceReducer.mock.calls[0][0]).toEqual({
-    bar: barReducer,
-    baz: bazReducer,
-    foo: fooReducer,
-  });
-});
diff --git a/__tests__/src/extend/pluginStore.test.js b/__tests__/src/extend/pluginStore.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..fa34f945c0f6665062bb261cafba5c809fda22ce
--- /dev/null
+++ b/__tests__/src/extend/pluginStore.test.js
@@ -0,0 +1,77 @@
+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('returns undefined if no plugin for target exist', () => {
+    pluginStore.storePlugins();
+    expect(pluginStore.getPlugins('target')).not.toBeDefined();
+  });
+
+  it('returns mode->plugins mapping for target', () => {
+    /** */
+    const component = x => x;
+
+    const plugins = [
+      { component, mode: 'wrap', target: 'Window' },
+      { component, mode: 'wrap', target: 'Window' },
+      { component, mode: 'add', target: 'Window' },
+      { component, mode: 'add', target: 'Window' },
+
+      { component, mode: 'wrap', target: 'TopBar' },
+      { component, mode: 'wrap', target: 'TopBar' },
+      { component, mode: 'add', target: 'TopBar' },
+      { component, mode: 'add', target: 'TopBar' },
+    ];
+
+    pluginStore.storePlugins(plugins);
+
+    expect(pluginStore.getPlugins('Window')).toEqual({
+      add: [
+        { component, mode: 'add', target: 'Window' },
+        { component, mode: 'add', target: 'Window' },
+      ],
+      wrap: [
+        { component, mode: 'wrap', target: 'Window' },
+        { component, mode: 'wrap', target: 'Window' },
+      ],
+    });
+
+    expect(pluginStore.getPlugins('TopBar')).toEqual({
+      add: [
+        { component, mode: 'add', target: 'TopBar' },
+        { component, mode: 'add', target: 'TopBar' },
+      ],
+      wrap: [
+        { component, mode: 'wrap', target: 'TopBar' },
+        { component, mode: 'wrap', target: 'TopBar' },
+      ],
+    });
+  });
+
+  // see also pluginValidation.test.js
+  it('filter out invalid plugins', () => {
+    /** */
+    const component = x => x;
+
+    const plugins = [
+      { component, mode: 'add', target: 'Window' },
+      { component, mode: 'LURK', target: 'Window' },
+    ];
+
+    pluginStore.storePlugins(plugins);
+
+    expect(pluginStore.getPlugins('Window')).toEqual({
+      add: [
+        { component, mode: 'add', target: 'Window' },
+      ],
+    });
+  });
+});
diff --git a/__tests__/src/extend/withPlugins.test.js b/__tests__/src/extend/withPlugins.test.js
index 08b33c5ebf75724efb01d9050caad16bdd62f281..1e3372b2501359e748c030215d3b331a239ed508 100644
--- a/__tests__/src/extend/withPlugins.test.js
+++ b/__tests__/src/extend/withPlugins.test.js
@@ -1,20 +1,20 @@
 import React from 'react';
-import { mount } from 'enzyme';
-import { withPlugins, PluginContext } from '../../../src/extend';
+import { shallow } from 'enzyme';
+import { withPlugins } from '../../../src/extend';
+import { pluginStore } from '../../../src/extend/pluginStore';
 
 
+jest.mock('../../../src/extend/pluginStore');
+
 /** Mock target component */
 const Target = props => <div>Hello</div>;
 
 /** create wrapper  */
-function createPluginHoc(pluginMap) {
+function createPluginHoc(plugins) {
+  pluginStore.getPlugins = () => plugins;
   const props = { bar: 2, foo: 1 };
   const PluginHoc = withPlugins('Target', Target);
-  return mount(
-    <PluginContext.Provider value={pluginMap}>
-      <PluginHoc {...props} />
-    </PluginContext.Provider>,
-  );
+  return shallow(<PluginHoc {...props} />);
 }
 
 describe('withPlugins', () => {
@@ -34,7 +34,7 @@ describe('withPlugins', () => {
 
 describe('PluginHoc: if no plugin exists for the target', () => {
   it('renders the target component', () => {
-    const hoc = createPluginHoc({});
+    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);
@@ -45,16 +45,14 @@ describe('PluginHoc: if wrap plugins exist for target', () => {
   it('renders the first wrap plugin and passes the target component and the target props to it', () => {
     /** */ const WrapPluginComponentA = props => <div>look i am a plugin</div>;
     /** */ const WrapPluginComponentB = props => <div>look i am a plugin</div>;
-    const pluginMap = {
-      Target: {
-        wrap: [
-          { component: WrapPluginComponentA, mode: 'wrap', target: 'Target' },
-          { component: WrapPluginComponentB, mode: 'wrap', target: 'Target' },
-        ],
-      },
+    const plugins = {
+      wrap: [
+        { component: WrapPluginComponentA, mode: 'wrap', target: 'Target' },
+        { component: WrapPluginComponentB, mode: 'wrap', target: 'Target' },
+      ],
     };
-    const hoc = createPluginHoc(pluginMap);
-    const selector = 'WrapPluginComponentA';
+    const hoc = createPluginHoc(plugins);
+    const selector = 'Connect(WrapPluginComponentA)';
     expect(hoc.find(selector).length).toBe(1);
     expect(hoc.find(selector).props().TargetComponent).toBe(Target);
     expect(hoc.find(selector).props().targetProps).toEqual({ bar: 2, foo: 1 });
@@ -66,20 +64,20 @@ describe('PluginHoc: if add plugins exist but no wrap plugin', () => {
     /** */ const AddPluginComponentA = props => <div>look i am a plugin</div>;
     /** */ const AddPluginComponentB = props => <div>look i am a plugin</div>;
     const plugins = {
-      Target: {
-        add: [
-          { component: AddPluginComponentA, mode: 'add', target: 'Target' },
-          { component: AddPluginComponentB, mode: 'add', target: 'Target' },
-        ],
-      },
+      add: [
+        { component: AddPluginComponentA, mode: 'add', target: 'Target' },
+        { component: AddPluginComponentB, mode: 'add', target: 'Target' },
+      ],
     };
     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]).toBe(AddPluginComponentA);
-    expect(hoc.find(selector).props().PluginComponents[1]).toBe(AddPluginComponentB);
+    expect(hoc.find(selector).props().PluginComponents[0].displayName)
+      .toBe('Connect(AddPluginComponentA)');
+    expect(hoc.find(selector).props().PluginComponents[1].displayName)
+      .toBe('Connect(AddPluginComponentB)');
   });
 });
 
@@ -90,19 +88,17 @@ describe('PluginHoc: if wrap plugins AND add plugins exist for target', () => {
     /** */ const AddPluginComponentA = props => <div>look i am a plugin</div>;
     /** */ const AddPluginComponentB = props => <div>look i am a plugin</div>;
     const plugins = {
-      Target: {
-        add: [
-          { component: AddPluginComponentA, mode: 'add', target: 'Target' },
-          { component: AddPluginComponentB, mode: 'add', target: 'Target' },
-        ],
-        wrap: [
-          { component: WrapPluginComponentA, mode: 'wrap', target: 'Target' },
-          { component: WrapPluginComponentB, mode: 'wrap', target: 'Target' },
-        ],
-      },
+      add: [
+        { component: AddPluginComponentA, mode: 'add', target: 'Target' },
+        { component: AddPluginComponentB, mode: 'add', target: 'Target' },
+      ],
+      wrap: [
+        { component: WrapPluginComponentA, mode: 'wrap', target: 'Target' },
+        { component: WrapPluginComponentB, mode: 'wrap', target: 'Target' },
+      ],
     };
     const hoc = createPluginHoc(plugins);
-    expect(hoc.find(WrapPluginComponentA).length).toBe(1);
+    expect(hoc.find('Connect(WrapPluginComponentA)').length).toBe(1);
     expect(hoc.find(Target).length).toBe(0);
   });
 });
diff --git a/__tests__/src/lib/MiradorViewer.test.js b/__tests__/src/lib/MiradorViewer.test.js
index 0df7c0e0a77228952615ce581ee8b4244eb9b779..b8592e40c24123209f449fcfe26bd26da2e82025 100644
--- a/__tests__/src/lib/MiradorViewer.test.js
+++ b/__tests__/src/lib/MiradorViewer.test.js
@@ -1,7 +1,9 @@
 import ReactDOM from 'react-dom';
+import { pluginStore } from '../../../src/extend/pluginStore';
 import MiradorViewer from '../../../src/lib/MiradorViewer';
 
 jest.unmock('react-i18next');
+jest.mock('../../../src/extend/pluginStore');
 jest.mock('react-dom');
 
 describe('MiradorViewer', () => {
@@ -21,6 +23,31 @@ describe('MiradorViewer', () => {
       expect(ReactDOM.render).toHaveBeenCalled();
     });
   });
+  describe('process plugins', () => {
+    it('should store plugins and set reducers to state', () => {
+      /** */ const fooReducer = (state = 0) => state;
+      /** */ const barReducer = (state = 0) => state;
+      /** */ const bazReducer = (state = 0) => state;
+      /** */ const plugins = [
+        {
+          reducers: {
+            bar: barReducer,
+            foo: fooReducer,
+          },
+        },
+        {
+          reducers: {
+            baz: bazReducer,
+          },
+        },
+      ];
+      instance = new MiradorViewer({}, plugins);
+      expect(pluginStore.storePlugins).toBeCalledWith(plugins);
+      expect(instance.store.getState().foo).toBeDefined();
+      expect(instance.store.getState().bar).toBeDefined();
+      expect(instance.store.getState().baz).toBeDefined();
+    });
+  });
   describe('processConfig', () => {
     it('transforms config values to actions to dispatch to store', () => {
       instance = new MiradorViewer({
diff --git a/src/extend/index.js b/src/extend/index.js
index 18c4065c501310884a0ea15c5f24f327dc3ba6e3..d534dcaffb6e8c4ed65d661bc2cb94c63836b39b 100644
--- a/src/extend/index.js
+++ b/src/extend/index.js
@@ -1,5 +1,3 @@
-export * from './pluginContext';
-export * from './pluginProvider';
-export * from './pluginPreprocessing';
-export * from './pluginValidation';
+export * from './pluginStore';
 export * from './withPlugins';
+export * from './pluginValidation';
diff --git a/src/extend/pluginContext.js b/src/extend/pluginContext.js
deleted file mode 100644
index 8e4d874591f2d81625adf0bf20bb3eae51973f21..0000000000000000000000000000000000000000
--- a/src/extend/pluginContext.js
+++ /dev/null
@@ -1,3 +0,0 @@
-import React from 'react';
-
-export const PluginContext = React.createContext();
diff --git a/src/extend/pluginPreprocessing.js b/src/extend/pluginPreprocessing.js
deleted file mode 100644
index 6bed9602bd70a9deda1493dd7f479e2e76f67159..0000000000000000000000000000000000000000
--- a/src/extend/pluginPreprocessing.js
+++ /dev/null
@@ -1,71 +0,0 @@
-import update from 'lodash/update';
-import { connect } from 'react-redux';
-import { validatePlugin } from '.';
-
-/**
- * Returns a mapping from targets to plugins and modes
- *
- * @param {Array} plugins
- * @return {Object} - looks like:
- *
- *  {
- *    'WorkspacePanel': {
- *      wrap:     [plugin3, ...],
- *      add:      [plugin4, ...],
- *    },
- *    ...
- *  }
- */
-export function createTargetToPluginMapping(plugins) {
-  return plugins.reduce((map, plugin) => (
-    update(map, [plugin.target, plugin.mode], x => [...x || [], plugin])
-  ), {});
-}
-
-/** */
-export function filterValidPlugins(plugins) {
-  const { validPlugins, invalidPlugins } = splitPluginsByValidation(plugins);
-  logInvalidPlugins(invalidPlugins);
-  return validPlugins;
-}
-
-/** */
-export function connectPluginsToStore(plugins) {
-  return plugins.map(plugin => (
-    { ...plugin, component: connectPluginComponent(plugin) }
-  ));
-}
-
-/** */
-export function addPluginReducersToStore(store, createRootReducer, plugins) {
-  const pluginReducers = getReducersFromPlugins(plugins);
-  store.replaceReducer(createRootReducer(pluginReducers));
-}
-
-/** */
-function splitPluginsByValidation(plugins) {
-  const splittedPlugins = { invalidPlugins: [], validPlugins: [] };
-  plugins.forEach(plugin => (
-    validatePlugin(plugin)
-      ? splittedPlugins.validPlugins.push(plugin)
-      : splittedPlugins.invalidPlugins.push(plugin)
-  ));
-  return splittedPlugins;
-}
-
-/** */
-function logInvalidPlugins(plugins) {
-  plugins.forEach(plugin => (
-    console.log(`Mirador: Plugin ${plugin.name} is not valid and was rejected.`)
-  ));
-}
-
-/** Connect plugin component to state */
-function connectPluginComponent(plugin) {
-  return connect(plugin.mapStateToProps, plugin.mapDispatchToProps)(plugin.component);
-}
-
-/**  */
-function getReducersFromPlugins(plugins) {
-  return plugins && plugins.reduce((acc, plugin) => ({ ...acc, ...plugin.reducers }), {});
-}
diff --git a/src/extend/pluginProvider.js b/src/extend/pluginProvider.js
deleted file mode 100644
index 73d2739b05b442f7b721f260777895c4db2ff4d5..0000000000000000000000000000000000000000
--- a/src/extend/pluginProvider.js
+++ /dev/null
@@ -1,43 +0,0 @@
-import React, { useContext, useEffect, useState } from 'react';
-import PropTypes from 'prop-types';
-import { ReactReduxContext } from 'react-redux';
-import {
-  PluginContext,
-  filterValidPlugins,
-  addPluginReducersToStore,
-  connectPluginsToStore,
-  createTargetToPluginMapping,
-} from '.';
-
-
-/**  */
-export function PluginProvider(props) {
-  const { store } = useContext(ReactReduxContext);
-  const { plugins, createRootReducer, children } = props;
-  const [pluginMap, setPluginMap] = useState({});
-
-  useEffect(() => {
-    const validPlugins = filterValidPlugins(plugins);
-    const connectedPlugins = connectPluginsToStore(validPlugins);
-    createRootReducer && addPluginReducersToStore(store, createRootReducer, validPlugins);
-    setPluginMap(createTargetToPluginMapping(connectedPlugins));
-  }, []);
-
-  return (
-    <PluginContext.Provider value={pluginMap}>
-      { children }
-    </PluginContext.Provider>
-  );
-}
-
-PluginProvider.propTypes = {
-  children: PropTypes.node,
-  createRootReducer: PropTypes.func,
-  plugins: PropTypes.array, // eslint-disable-line react/forbid-prop-types
-};
-
-PluginProvider.defaultProps = {
-  children: null,
-  createRootReducer: null,
-  plugins: [],
-};
diff --git a/src/extend/pluginStore.js b/src/extend/pluginStore.js
new file mode 100644
index 0000000000000000000000000000000000000000..0b191b3dd1e59a54f5bd57c6b81d912b5b95fb83
--- /dev/null
+++ b/src/extend/pluginStore.js
@@ -0,0 +1,71 @@
+import update from 'lodash/update';
+import { validatePlugin } from '.';
+
+export const pluginStore = {
+  /**
+  * Get plugins for target
+  *
+  * @param {String} targetName
+  * @return {Object | undefined } - looks like:
+  *
+  *  {
+  *    wrap:     [plugin1, ...],
+  *    add:      [plugin2, ...],
+  *  }
+  */
+  getPlugins(target) {
+    return this.pluginMap[target];
+  },
+  /**
+   * Store Plugins
+   *
+   * @param {Array} plugins
+   */
+  storePlugins(plugins = []) {
+    const { validPlugins, invalidPlugins } = filterPlugins(plugins);
+    logInvalidPlugins(invalidPlugins);
+    this.pluginMap = mapPlugins(validPlugins);
+  },
+};
+
+/**
+ * Returns a mapping from plugins to targets and modes
+ *
+ * @param {Array} plugins
+ * @return {Object} - looks like:
+ *
+ *
+ *  {
+ *    'WorkspacePanel': {
+ *      wrap:     [plugin3, ...],
+ *      add:      [plugin4, ...],
+ *    },
+ *    'Window': {
+ *      wrap:     [plugin3, ...],
+ *      add:      [plugin4, ...],
+ *    }
+ *  }
+ */
+function mapPlugins(plugins) {
+  return plugins.reduce((map, plugin) => (
+    update(map, [plugin.target, plugin.mode], x => [...x || [], plugin])
+  ), {});
+}
+
+/** */
+function filterPlugins(plugins) {
+  const filteredPlugins = { invalidPlugins: [], validPlugins: [] };
+  plugins.forEach(plugin => (
+    validatePlugin(plugin)
+      ? filteredPlugins.validPlugins.push(plugin)
+      : filteredPlugins.invalidPlugins.push(plugin)
+  ));
+  return filteredPlugins;
+}
+
+/** */
+function logInvalidPlugins(plugins) {
+  plugins.forEach(plugin => (
+    console.log(`Mirador: Plugin ${plugin.name} is not valid and was rejected.`)
+  ));
+}
diff --git a/src/extend/withPlugins.js b/src/extend/withPlugins.js
index 8d78d0ef0baaa1ff96667d572eeb6777474272ea..2f79734818156b96f4cb81749de4f4286cdc5340 100644
--- a/src/extend/withPlugins.js
+++ b/src/extend/withPlugins.js
@@ -1,28 +1,30 @@
-import React, { useContext } from 'react';
+import React, { Component } from 'react';
 import curry from 'lodash/curry';
 import isEmpty from 'lodash/isEmpty';
-import { PluginContext } from '.';
-
+import { connect } from 'react-redux';
+import { pluginStore } from '.';
 
 /** withPlugins should be the innermost HOC */
 function _withPlugins(targetName, TargetComponent) { // eslint-disable-line no-underscore-dangle
-  /** */
-  function PluginHoc(props) {
-    const pluginMap = useContext(PluginContext);
-    const plugins = pluginMap[targetName];
+  /** plugin wrapper hoc */
+  class PluginHoc extends Component {
+    /** render */
+    render() { // eslint-disable-line consistent-return
+      const plugins = pluginStore.getPlugins(targetName);
 
-    if (isEmpty(plugins)) {
-      return <TargetComponent {...props} />;
-    }
+      if (isEmpty(plugins)) {
+        return <TargetComponent {...this.props} />;
+      }
 
-    if (!isEmpty(plugins.wrap)) {
-      const PluginComponent = plugins.wrap[0].component;
-      return <PluginComponent targetProps={props} TargetComponent={TargetComponent} />;
-    }
+      if (!isEmpty(plugins.wrap)) {
+        const WrapPluginComponent = connectPluginComponent(plugins.wrap[0]);
+        return <WrapPluginComponent targetProps={this.props} TargetComponent={TargetComponent} />;
+      }
 
-    if (!isEmpty(plugins.add)) {
-      const PluginComponents = plugins.add.map(plugin => plugin.component);
-      return <TargetComponent {...props} PluginComponents={PluginComponents} />;
+      if (!isEmpty(plugins.add)) {
+        const AddPluginComponents = plugins.add.map(plugin => connectPluginComponent(plugin));
+        return <TargetComponent {...this.props} PluginComponents={AddPluginComponents} />;
+      }
     }
   }
 
@@ -30,5 +32,10 @@ function _withPlugins(targetName, TargetComponent) { // eslint-disable-line no-u
   return PluginHoc;
 }
 
+/** Connect plugin component to state */
+function connectPluginComponent(plugin) {
+  return connect(plugin.mapStateToProps, plugin.mapDispatchToProps)(plugin.component);
+}
+
 /** withPlugins('MyComponent')(MyComponent) */
 export const withPlugins = curry(_withPlugins);
diff --git a/src/lib/MiradorViewer.js b/src/lib/MiradorViewer.js
index 1cbcb7e04c539d6647bed7236034041db4dd9b22..91c5544a74cf762c40ade319b9723ec911628687 100644
--- a/src/lib/MiradorViewer.js
+++ b/src/lib/MiradorViewer.js
@@ -2,10 +2,9 @@ import React from 'react';
 import ReactDOM from 'react-dom';
 import { Provider } from 'react-redux';
 import deepmerge from 'deepmerge';
-import { PluginProvider } from '../extend';
 import App from '../containers/App';
+import { pluginStore } from '../extend';
 import createStore from '../state/createStore';
-import createRootReducer from '../state/reducers/rootReducer';
 import * as actions from '../state/actions';
 import settings from '../config/settings';
 
@@ -16,7 +15,9 @@ class MiradorViewer {
   /**
    */
   constructor(config, plugins) {
-    this.store = createStore();
+    pluginStore.storePlugins(plugins);
+    const pluginReducers = getReducersFromPlugins(plugins);
+    this.store = createStore(pluginReducers);
     this.config = config;
     this.processConfig();
     const viewer = {
@@ -26,9 +27,7 @@ class MiradorViewer {
 
     ReactDOM.render(
       <Provider store={this.store}>
-        <PluginProvider plugins={plugins} createRootReducer={createRootReducer}>
-          <App />
-        </PluginProvider>
+        <App />
       </Provider>,
       document.getElementById(config.id),
     );
@@ -74,4 +73,9 @@ class MiradorViewer {
   }
 }
 
+/** Return reducers from plugins */
+function getReducersFromPlugins(plugins) {
+  return plugins && plugins.reduce((acc, plugin) => ({ ...acc, ...plugin.reducers }), {});
+}
+
 export default MiradorViewer;