diff --git a/apps/web/src/app/App.tsx b/apps/web/src/app/App.tsx
index 8d1795b1fc6cda164313635ba9ea0c1fe7c1556f..0f6d822a6cd6c7a2a2e9817ecb104f32ee8e3649 100644
--- a/apps/web/src/app/App.tsx
+++ b/apps/web/src/app/App.tsx
@@ -7,6 +7,7 @@ import {
   useQuerybuilderSettings,
   useSessionCache,
 } from '@graphpolaris/shared/lib/data-access';
+import { setCurrentTheme } from '@graphpolaris/shared/lib/data-access/store/configSlice';
 import { resetGraphQueryResults, queryingBackend } from '@graphpolaris/shared/lib/data-access/store/graphQueryResultSlice';
 import { Query2BackendQuery, QueryMultiGraph } from '@graphpolaris/shared/lib/querybuilder';
 import { Navbar } from '../components/navbar/navbar';
@@ -52,6 +53,10 @@ export function App(props: App) {
     }
   }, [props]);
 
+  window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => {
+    dispatch(setCurrentTheme(event.matches));
+  });
+
   const [authCheck, setAuthCheck] = useState(false);
   const [tab, setTab] = useState<SideNavTab>('Schema');
   // const [visFullSize, setVisFullSize] = useState<boolean>(false);
diff --git a/libs/shared/lib/components/color-mode/index.tsx b/libs/shared/lib/components/color-mode/index.tsx
index 5c8a69580f656a3527e2f1e17aa5539b15c60d1b..d9f9ecb8877ce5eb8507d2b12b6af04d5a1e2adc 100644
--- a/libs/shared/lib/components/color-mode/index.tsx
+++ b/libs/shared/lib/components/color-mode/index.tsx
@@ -22,12 +22,16 @@ const ColorMode = () => {
 
   // Function to toggle the theme
   const toggleTheme = () => {
-    const themes = [Theme.light, Theme.dark];
-
+    const themes = [
+      Theme.system,
+      Theme.light,
+      Theme.dark,
+    ];
+    
     const newTheme = themes[(themes.indexOf(config.theme) + 1) % themes.length];
     dispatch(setTheme(newTheme));
   };
-  const iconComponent = config.theme === Theme.dark ? 'icon-[ic--baseline-dark-mode]' : 'icon-[ic--baseline-light-mode]';
+  const iconComponent = config.theme === Theme.dark ? 'icon-[ic--baseline-dark-mode]' : config.theme === Theme.light ? 'icon-[ic--baseline-light-mode]' : 'icon-[ic--baseline-auto-mode]';
 
   return (
     <TooltipProvider delayDuration={0}>
@@ -36,7 +40,7 @@ const ColorMode = () => {
           <Button variant="ghost" size="sm" iconComponent={iconComponent} onClick={toggleTheme} />
         </TooltipTrigger>
         <TooltipContent>
-          <p>{`Switch to ${config.theme === Theme.dark ? 'light' : 'dark'}-mode`}</p>
+          <p>{`Currently on ${config.theme.split('-')[0]} theme`}</p>
         </TooltipContent>
       </Tooltip>
     </TooltipProvider>
diff --git a/libs/shared/lib/data-access/store/configSlice.ts b/libs/shared/lib/data-access/store/configSlice.ts
index f79c4d3f932773b554edadefebe0b4ee59981f2d..932a281d357088f7669f0616c5c9269477535df6 100644
--- a/libs/shared/lib/data-access/store/configSlice.ts
+++ b/libs/shared/lib/data-access/store/configSlice.ts
@@ -2,6 +2,7 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit';
 import type { RootState } from './store';
 
 export enum Theme {
+  system = 'system-mode',
   light = 'light-mode',
   dark = 'dark-mode',
 }
@@ -9,6 +10,7 @@ export enum Theme {
 // Define the initial state using that type
 export type ConfigStateI = {
   theme: Theme;
+  currentTheme: Theme;
   autoSendQueries: boolean;
   errors: string[];
   warnings: string[];
@@ -16,7 +18,8 @@ export type ConfigStateI = {
   successes: string[];
 };
 export const initialState: ConfigStateI = {
-  theme: localStorage.getItem('theme') as Theme ?? Theme.light,
+  theme: localStorage.getItem('theme') as Theme ?? Theme.system,
+  currentTheme: resolveTheme(localStorage.getItem('theme') as Theme ?? Theme.system),
   autoSendQueries: true,
   errors: [],
   warnings: [],
@@ -24,6 +27,14 @@ export const initialState: ConfigStateI = {
   successes: [],
 };
 
+function resolveTheme(theme: Theme) {
+  if (theme == Theme.system) {
+    const prefersDarkMode = window.matchMedia('(prefers-color-scheme: dark)').matches;
+    return prefersDarkMode ? Theme.dark : Theme.light;
+  }
+  return theme
+}
+
 export const configSlice = createSlice({
   name: 'config',
   // `createSlice` will infer the state type from the `initialState` argument
@@ -58,11 +69,17 @@ export const configSlice = createSlice({
     setTheme: (state, action: PayloadAction<Theme>) => {
       localStorage.setItem('theme', action.payload);
       state.theme = action.payload;
+      state.currentTheme = resolveTheme(action.payload);
+    },
+    setCurrentTheme: (state, action: PayloadAction<boolean>) => {
+      if (state.theme === Theme.system) {
+        state.currentTheme = action.payload ? Theme.dark : Theme.light;
+      }
     },
   },
 });
 
-export const { addError, removeLastError, addWarning, removeLastWarning, addSuccess, removeLastSuccess, addInfo, removeLastInfo, setTheme } =
+export const { addError, removeLastError, addWarning, removeLastWarning, addSuccess, removeLastSuccess, addInfo, removeLastInfo, setTheme, setCurrentTheme } =
   configSlice.actions;
 
 // Other code such as selectors can use the imported `RootState` type
diff --git a/libs/shared/lib/vis/visualizations/nodelinkvis/components/NLPixi.tsx b/libs/shared/lib/vis/visualizations/nodelinkvis/components/NLPixi.tsx
index 8dd8460eb2118fab9f1d53735a2bb0edff15dcfb..b8d262a2ec12d469e304dd320bf4510b6cb08754 100644
--- a/libs/shared/lib/vis/visualizations/nodelinkvis/components/NLPixi.tsx
+++ b/libs/shared/lib/vis/visualizations/nodelinkvis/components/NLPixi.tsx
@@ -43,7 +43,7 @@ export const NLPixi = forwardRef((props: Props, refExternal) => {
 
   useEffect(() => {
     update();
-  }, [globalConfig.theme]);
+  }, [globalConfig.currentTheme]);
 
   const app = useMemo(
     () =>
@@ -318,7 +318,7 @@ export const NLPixi = forwardRef((props: Props, refExternal) => {
 
     getBackgroundColor() {
       // Colors corresponding to .bg-light class
-      return globalConfig.theme === Theme.dark ? 0x121621 : 0xffffff;
+      return globalConfig.currentTheme === Theme.dark ? 0x121621 : 0xffffff;
     },
   }));