diff --git a/apps/web-graphpolaris/src/app/app.tsx b/apps/web-graphpolaris/src/app/app.tsx
index 7230795259a44bfb926a5cb496e3639ba73e264c..c33f6c28dfe1585435a0388de4f5f5e9c1a1dac4 100644
--- a/apps/web-graphpolaris/src/app/app.tsx
+++ b/apps/web-graphpolaris/src/app/app.tsx
@@ -1,42 +1,20 @@
 // eslint-disable-next-line @typescript-eslint/no-unused-vars
-import * as React from 'react';
-import { createTheme, ThemeProvider } from '@mui/material/styles';
 import {
   assignNewGraphQueryResult,
+  changeDataPointColors,
   useAppDispatch,
-  useColorPalette,
 } from '@graphpolaris/shared/data-access/store';
 import GridLayout from 'react-grid-layout';
 import Panel from '../components/panels/panel';
 import { RawJSONVis } from '../components/visualisations/rawjsonvis/rawjsonvis';
 import SemanticSubstrates from '../components/visualisations/semanticsubstrates/semanticsubstrates';
-import { Theme, Palette } from '@mui/material/styles';
-
-declare module '@mui/material/styles' {
-  interface PaletteOptions {
-    dataPointColors: React.CSSProperties['color'][];
-  }
-}
+import { OurThemeProvider } from '@graphpolaris/shared/data-access/theme';
 
 export function App() {
   const dispatch = useAppDispatch();
-  const colorPalette = useColorPalette();
-
-  // Create a new theme when our custom color palette in redux changed
-  const theme = React.useMemo(
-    () =>
-      // Mapping our palette slice data to the mui theme could be a usecase
-      createTheme({
-        palette: {
-          primary: { main: colorPalette.primary.main },
-          dataPointColors: colorPalette.dataPointColors,
-        },
-      }),
-    [colorPalette]
-  );
 
   return (
-    <ThemeProvider theme={theme}>
+    <OurThemeProvider>
       <GridLayout
         className="layout"
         cols={10}
@@ -98,7 +76,7 @@ export function App() {
           <Panel content="History Channel" color="purple"></Panel>
         </div>
       </GridLayout>
-    </ThemeProvider>
+    </OurThemeProvider>
   );
 }
 
diff --git a/apps/web-graphpolaris/src/components/panels/panel.tsx b/apps/web-graphpolaris/src/components/panels/panel.tsx
index bf43cca74d91330d0c8a92d807445b21c0035a8d..5189e4d410f05b865992f6a272fd371c550f91e3 100644
--- a/apps/web-graphpolaris/src/components/panels/panel.tsx
+++ b/apps/web-graphpolaris/src/components/panels/panel.tsx
@@ -1,5 +1,6 @@
 import styled from 'styled-components';
 import { ReactNode } from 'react';
+import { useTheme } from '@mui/material/styles';
 interface Props {
   content: string;
   color: string;
@@ -27,10 +28,14 @@ const Content = styled.div`
 `;
 
 const Panel = (props: Props) => {
+  const theme = useTheme();
+
   return (
     <Wrapper color={props.color}>
       <Content>
-        <h1>{props.content}</h1>
+        <h1 style={{ backgroundColor: theme.palette.dataPointColors[1] }}>
+          {props.content}
+        </h1>
         {props.children}
       </Content>
     </Wrapper>
diff --git a/apps/web-graphpolaris/src/components/visualisations/semanticsubstrates/semanticsubstrates.tsx b/apps/web-graphpolaris/src/components/visualisations/semanticsubstrates/semanticsubstrates.tsx
index 9c2609a70cc189898b711c6d5fece7e4b1308a02..04a068232a2697841d2e12361904999a8da2f036 100644
--- a/apps/web-graphpolaris/src/components/visualisations/semanticsubstrates/semanticsubstrates.tsx
+++ b/apps/web-graphpolaris/src/components/visualisations/semanticsubstrates/semanticsubstrates.tsx
@@ -1,10 +1,9 @@
-import { styled, Theme } from '@mui/material/styles';
+import { styled, Theme, useTheme } from '@mui/material/styles';
 import Box from '@mui/material/Box';
 import { useDispatch } from 'react-redux';
 import {
   changeDataPointColors,
   changePrimary,
-  useColorPalette,
 } from '@graphpolaris/shared/data-access/store';
 
 // Basically a styled-component
@@ -14,7 +13,7 @@ const Div = styled('div')(({ theme }) => ({
 
 const SemanticSubstrates = () => {
   const dispatch = useDispatch();
-  const colorPalette = useColorPalette();
+  const theme = useTheme();
 
   return (
     <>
@@ -24,7 +23,7 @@ const SemanticSubstrates = () => {
       <Box
         sx={{
           // Using our custom palette dataPointColors property, cast theme to any because Theme doesn't know of this custom property
-          backgroundColor: (theme: any) => theme.palette.dataPointColors[0],
+          backgroundColor: (theme: Theme) => theme.palette.dataPointColors[0],
         }}
       >
         <h1>semantic substrates</h1>
@@ -36,21 +35,36 @@ const SemanticSubstrates = () => {
         type="color"
         id="head"
         name="head"
-        value={colorPalette.primary.main}
+        value={theme.palette.primary.main}
       />
       <input
         onChange={(v) =>
           dispatch(
             changeDataPointColors([
               v.currentTarget.value,
-              ...colorPalette.dataPointColors.slice(1),
+              ...theme.palette.dataPointColors.slice(1),
             ])
           )
         }
         type="color"
         id="head"
         name="head"
-        value={colorPalette.dataPointColors[0]}
+        value={theme.palette.dataPointColors[0]}
+      />
+      <input
+        onChange={(v) =>
+          dispatch(
+            changeDataPointColors([
+              theme.palette.dataPointColors[0],
+              v.currentTarget.value,
+              ...theme.palette.dataPointColors.slice(2),
+            ])
+          )
+        }
+        type="color"
+        id="head"
+        name="head"
+        value={theme.palette.dataPointColors[1]}
       />
     </>
   );
diff --git a/libs/shared/data-access/store/src/index.ts b/libs/shared/data-access/store/src/index.ts
index b798d7f530615da227699bbe3004696ab390cc83..d5a3cbf88459585818d0a4ff2c3e3ad2bd9ade65 100644
--- a/libs/shared/data-access/store/src/index.ts
+++ b/libs/shared/data-access/store/src/index.ts
@@ -6,7 +6,15 @@ export {
   selectGraphQueryResultNodes,
   assignNewGraphQueryResult,
 } from './lib/graphQueryResultSlice';
-export { changePrimary, changeDataPointColors } from './lib/colorPaletteSlice';
+export {
+  changePrimary,
+  changeDataPointColors,
+  selectColorPaletteConfig,
+} from './lib/colorPaletteConfigSlice';
 
 // Exported types
 export type { Node, Edge, GraphQueryResult } from './lib/graphQueryResultSlice';
+export type {
+  ColorPaletteConfig,
+  ExtraColorsForMui5,
+} from './lib/colorPaletteConfigSlice';
diff --git a/libs/shared/data-access/store/src/lib/colorPaletteSlice.ts b/libs/shared/data-access/store/src/lib/colorPaletteConfigSlice.ts
similarity index 50%
rename from libs/shared/data-access/store/src/lib/colorPaletteSlice.ts
rename to libs/shared/data-access/store/src/lib/colorPaletteConfigSlice.ts
index 753a4b7d6f8fdcf29cc9ebced56fef2b03ba3dc2..b311ccee957853b4e5b1a57b7b80f8d2f15c6d13 100644
--- a/libs/shared/data-access/store/src/lib/colorPaletteSlice.ts
+++ b/libs/shared/data-access/store/src/lib/colorPaletteConfigSlice.ts
@@ -1,17 +1,30 @@
 import { createSlice, PayloadAction } from '@reduxjs/toolkit';
 import type { RootState } from './store';
 
-// This looks very much like the mui Palette,
+/** Extra properties that are not present in the default PaletteOptions of mui. */
+export interface ExtraColorsForMui5 {
+  /** Colors that can be used for data visualisation, e.g. nodes, edges */
+  dataPointColors: string[];
+}
+
+/** Our custom color palette config. */
+export interface ColorPaletteConfig extends ExtraColorsForMui5 {
+  primary: {
+    main: string;
+  };
+}
+
+// This looks very much like the mui Palette interface,
 // But we don't reference that type directly here to stay decoupled
-export const initialState = {
+export const initialState: ColorPaletteConfig = {
   dataPointColors: ['#ff0000', '#00ff00', '#0000ff'],
   primary: {
     main: '#9999ff',
   },
 };
 
-export const colorPaletteSlice = createSlice({
-  name: 'colorPalette',
+export const colorPaletteConfigSlice = createSlice({
+  name: 'colorPaletteConfig',
   // `createSlice` will infer the state type from the `initialState` argument
   initialState,
   reducers: {
@@ -25,9 +38,10 @@ export const colorPaletteSlice = createSlice({
 });
 
 export const { changePrimary, changeDataPointColors } =
-  colorPaletteSlice.actions;
+  colorPaletteConfigSlice.actions;
 
 // Select the schema and convert it to a graphology object
-export const selectColorPalette = (state: RootState) => state.colorPalette;
+export const selectColorPaletteConfig = (state: RootState) =>
+  state.colorPaletteConfig;
 
-export default colorPaletteSlice.reducer;
+export default colorPaletteConfigSlice.reducer;
diff --git a/libs/shared/data-access/store/src/lib/hooks.ts b/libs/shared/data-access/store/src/lib/hooks.ts
index cc8af8bf1caacfea364e4a878b4c80adf5cf6879..df0faef46e155463bea444790b3ba91dcc076b76 100644
--- a/libs/shared/data-access/store/src/lib/hooks.ts
+++ b/libs/shared/data-access/store/src/lib/hooks.ts
@@ -1,5 +1,4 @@
 import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux';
-import { selectColorPalette } from './colorPaletteSlice';
 import { selectGraphQueryResult } from './graphQueryResultSlice';
 import { selectSchema } from './schemaSlice';
 import type { RootState, AppDispatch } from './store';
@@ -13,5 +12,3 @@ export const useGraphQueryResult = () => useAppSelector(selectGraphQueryResult);
 
 // Gives the schema form the store (as a graphology object)
 export const useSchema = () => useAppSelector(selectSchema);
-
-export const useColorPalette = () => useAppSelector(selectColorPalette);
diff --git a/libs/shared/data-access/store/src/lib/store.ts b/libs/shared/data-access/store/src/lib/store.ts
index 3ecb3ec20ebd75c7412904f46c192d23fb217538..7198337bde3e8b98b11d6336552743c71d8e413a 100644
--- a/libs/shared/data-access/store/src/lib/store.ts
+++ b/libs/shared/data-access/store/src/lib/store.ts
@@ -1,5 +1,5 @@
 import { configureStore } from '@reduxjs/toolkit';
-import colorPaletteSlice from './colorPaletteSlice';
+import colorPaletteConfigSlice from './colorPaletteConfigSlice';
 import graphQueryResultSlice from './graphQueryResultSlice';
 import schemaSlice from './schemaSlice';
 
@@ -7,7 +7,7 @@ export const store = configureStore({
   reducer: {
     graphQueryResult: graphQueryResultSlice,
     schema: schemaSlice,
-    colorPalette: colorPaletteSlice,
+    colorPaletteConfig: colorPaletteConfigSlice,
   },
 });
 
diff --git a/libs/shared/data-access/theme/.babelrc b/libs/shared/data-access/theme/.babelrc
new file mode 100644
index 0000000000000000000000000000000000000000..ccae900be42788285eb6e1b3a2af4b81f56f14fe
--- /dev/null
+++ b/libs/shared/data-access/theme/.babelrc
@@ -0,0 +1,12 @@
+{
+  "presets": [
+    [
+      "@nrwl/react/babel",
+      {
+        "runtime": "automatic",
+        "useBuiltIns": "usage"
+      }
+    ]
+  ],
+  "plugins": []
+}
diff --git a/libs/shared/data-access/theme/.eslintrc.json b/libs/shared/data-access/theme/.eslintrc.json
new file mode 100644
index 0000000000000000000000000000000000000000..3cd64217595c25dc61c2fd055ec4dbe21195a3e3
--- /dev/null
+++ b/libs/shared/data-access/theme/.eslintrc.json
@@ -0,0 +1,18 @@
+{
+  "extends": ["plugin:@nrwl/nx/react", "../../../../.eslintrc.json"],
+  "ignorePatterns": ["!**/*"],
+  "overrides": [
+    {
+      "files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
+      "rules": {}
+    },
+    {
+      "files": ["*.ts", "*.tsx"],
+      "rules": {}
+    },
+    {
+      "files": ["*.js", "*.jsx"],
+      "rules": {}
+    }
+  ]
+}
diff --git a/libs/shared/data-access/theme/README.md b/libs/shared/data-access/theme/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..bbf79085703dc9357fa05de431cfbba189046124
--- /dev/null
+++ b/libs/shared/data-access/theme/README.md
@@ -0,0 +1,7 @@
+# shared-data-access-theme
+
+This library was generated with [Nx](https://nx.dev).
+
+## Running unit tests
+
+Run `nx test shared-data-access-theme` to execute the unit tests via [Jest](https://jestjs.io).
diff --git a/libs/shared/data-access/theme/jest.config.js b/libs/shared/data-access/theme/jest.config.js
new file mode 100644
index 0000000000000000000000000000000000000000..0fca299e2f20e17cf1b441337ee26e44e06b25c5
--- /dev/null
+++ b/libs/shared/data-access/theme/jest.config.js
@@ -0,0 +1,9 @@
+module.exports = {
+  displayName: 'shared-data-access-theme',
+  preset: '../../../../jest.preset.js',
+  transform: {
+    '^.+\\.[tj]sx?$': 'babel-jest',
+  },
+  moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
+  coverageDirectory: '../../../../coverage/libs/shared/data-access/theme',
+};
diff --git a/libs/shared/data-access/theme/project.json b/libs/shared/data-access/theme/project.json
new file mode 100644
index 0000000000000000000000000000000000000000..18f65df2f249ed94da565e21e9b9d9223f6307cd
--- /dev/null
+++ b/libs/shared/data-access/theme/project.json
@@ -0,0 +1,25 @@
+{
+  "root": "libs/shared/data-access/theme",
+  "sourceRoot": "libs/shared/data-access/theme/src",
+  "projectType": "library",
+  "tags": [],
+  "targets": {
+    "lint": {
+      "executor": "@nrwl/linter:eslint",
+      "outputs": ["{options.outputFile}"],
+      "options": {
+        "lintFilePatterns": [
+          "libs/shared/data-access/theme/**/*.{ts,tsx,js,jsx}"
+        ]
+      }
+    },
+    "test": {
+      "executor": "@nrwl/jest:jest",
+      "outputs": ["coverage/libs/shared/data-access/theme"],
+      "options": {
+        "jestConfig": "libs/shared/data-access/theme/jest.config.js",
+        "passWithNoTests": true
+      }
+    }
+  }
+}
diff --git a/libs/shared/data-access/theme/src/index.ts b/libs/shared/data-access/theme/src/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..fae1f6948cf3d9f4fd40ea0c309bf39ea9f07f89
--- /dev/null
+++ b/libs/shared/data-access/theme/src/index.ts
@@ -0,0 +1 @@
+export * from './lib/ourThemeProvider';
diff --git a/libs/shared/data-access/theme/src/lib/mapColorsConfigToMuiTheme.ts b/libs/shared/data-access/theme/src/lib/mapColorsConfigToMuiTheme.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f94556c8842f61c8588bf38aa89295ed3920bc2b
--- /dev/null
+++ b/libs/shared/data-access/theme/src/lib/mapColorsConfigToMuiTheme.ts
@@ -0,0 +1,14 @@
+import { ColorPaletteConfig } from '@graphpolaris/shared/data-access/store';
+import { ThemeOptions } from '@mui/material/styles';
+
+/** Maps our color palette config (stored in redux) to the mui 5 theme format */
+export default function MapColorsConfigToMuiTheme(
+  colorsConfig: ColorPaletteConfig
+): ThemeOptions {
+  return {
+    palette: {
+      primary: { main: colorsConfig.primary.main },
+      dataPointColors: colorsConfig.dataPointColors,
+    },
+  };
+}
diff --git a/libs/shared/data-access/theme/src/lib/ourThemeProvider.tsx b/libs/shared/data-access/theme/src/lib/ourThemeProvider.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..04f36156807eafc3dcf4d4f569da172f00792d38
--- /dev/null
+++ b/libs/shared/data-access/theme/src/lib/ourThemeProvider.tsx
@@ -0,0 +1,35 @@
+import React, { ReactNode } from 'react';
+import {
+  ExtraColorsForMui5,
+  selectColorPaletteConfig,
+  useAppSelector,
+} from '@graphpolaris/shared/data-access/store';
+import { createTheme, ThemeProvider } from '@mui/material/styles';
+import MapColorsConfigToMuiTheme from './mapColorsConfigToMuiTheme';
+
+// Add custom theme variables to the mui theme types
+declare module '@mui/material/styles' {
+  interface Palette extends ExtraColorsForMui5 {} // eslint-disable-line
+  interface Theme {
+    palette: Palette;
+  }
+  interface PaletteOptions extends Partial<ExtraColorsForMui5> {} // eslint-disable-line
+  interface ThemeOptions {
+    palette?: PaletteOptions;
+  }
+}
+
+export function OurThemeProvider({ children }: { children: ReactNode }) {
+  const colorPaletteConfig = useAppSelector(selectColorPaletteConfig);
+
+  // Create a new theme when our custom color palette in redux changed
+  const theme = React.useMemo(
+    () =>
+      // Map our color palette config (stored in redux) to the mui 5 format
+      createTheme(MapColorsConfigToMuiTheme(colorPaletteConfig)),
+    [colorPaletteConfig]
+  );
+
+  return <ThemeProvider theme={theme}>{children}</ThemeProvider>;
+}
+export default OurThemeProvider;
diff --git a/libs/shared/data-access/theme/tsconfig.json b/libs/shared/data-access/theme/tsconfig.json
new file mode 100644
index 0000000000000000000000000000000000000000..3512bf7afeea1bf2e5fdb72b7dea8114f6c9fbe1
--- /dev/null
+++ b/libs/shared/data-access/theme/tsconfig.json
@@ -0,0 +1,25 @@
+{
+  "extends": "../../../../tsconfig.base.json",
+  "compilerOptions": {
+    "jsx": "react-jsx",
+    "allowJs": true,
+    "esModuleInterop": true,
+    "allowSyntheticDefaultImports": true,
+    "forceConsistentCasingInFileNames": true,
+    "strict": true,
+    "noImplicitOverride": true,
+    "noPropertyAccessFromIndexSignature": true,
+    "noImplicitReturns": true,
+    "noFallthroughCasesInSwitch": true
+  },
+  "files": [],
+  "include": [],
+  "references": [
+    {
+      "path": "./tsconfig.lib.json"
+    },
+    {
+      "path": "./tsconfig.spec.json"
+    }
+  ]
+}
diff --git a/libs/shared/data-access/theme/tsconfig.lib.json b/libs/shared/data-access/theme/tsconfig.lib.json
new file mode 100644
index 0000000000000000000000000000000000000000..1ab8e06a7111b168e84debca80bb4ac82f72f2aa
--- /dev/null
+++ b/libs/shared/data-access/theme/tsconfig.lib.json
@@ -0,0 +1,22 @@
+{
+  "extends": "./tsconfig.json",
+  "compilerOptions": {
+    "outDir": "../../../../dist/out-tsc",
+    "types": ["node"]
+  },
+  "files": [
+    "../../../../node_modules/@nrwl/react/typings/cssmodule.d.ts",
+    "../../../../node_modules/@nrwl/react/typings/image.d.ts"
+  ],
+  "exclude": [
+    "**/*.spec.ts",
+    "**/*.test.ts",
+    "**/*.spec.tsx",
+    "**/*.test.tsx",
+    "**/*.spec.js",
+    "**/*.test.js",
+    "**/*.spec.jsx",
+    "**/*.test.jsx"
+  ],
+  "include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"]
+}
diff --git a/libs/shared/data-access/theme/tsconfig.spec.json b/libs/shared/data-access/theme/tsconfig.spec.json
new file mode 100644
index 0000000000000000000000000000000000000000..315a5b0bbebaca96617a8dd5353901287ebd8e68
--- /dev/null
+++ b/libs/shared/data-access/theme/tsconfig.spec.json
@@ -0,0 +1,19 @@
+{
+  "extends": "./tsconfig.json",
+  "compilerOptions": {
+    "outDir": "../../../../dist/out-tsc",
+    "module": "commonjs",
+    "types": ["jest", "node"]
+  },
+  "include": [
+    "**/*.test.ts",
+    "**/*.spec.ts",
+    "**/*.test.tsx",
+    "**/*.spec.tsx",
+    "**/*.test.js",
+    "**/*.spec.js",
+    "**/*.test.jsx",
+    "**/*.spec.jsx",
+    "**/*.d.ts"
+  ]
+}
diff --git a/tsconfig.base.json b/tsconfig.base.json
index 5a2caf532de87019c51c475c16870bedb9fb4e9e..03fe56931d7eb9a85b6eb8aed1e97d26df900908 100644
--- a/tsconfig.base.json
+++ b/tsconfig.base.json
@@ -17,6 +17,9 @@
     "paths": {
       "@graphpolaris/shared/data-access/store": [
         "libs/shared/data-access/store/src/index.ts"
+      ],
+      "@graphpolaris/shared/data-access/theme": [
+        "libs/shared/data-access/theme/src/index.ts"
       ]
     }
   },
diff --git a/workspace.json b/workspace.json
index 1a59e05a31f38abe3f9085968e95163374b70590..93d09187b3a59f7fce4dcf30de996a7fd802b329 100644
--- a/workspace.json
+++ b/workspace.json
@@ -2,6 +2,7 @@
   "version": 2,
   "projects": {
     "shared-data-access-store": "libs/shared/data-access/store",
+    "shared-data-access-theme": "libs/shared/data-access/theme",
     "web-graphpolaris": "apps/web-graphpolaris",
     "web-graphpolaris-e2e": "apps/web-graphpolaris-e2e"
   }