diff --git a/frontend/package.json b/frontend/package.json
index b6a0a45..5c2f769 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -21,6 +21,7 @@
"lucide-react": "^0.453.0",
"next": "15.0.3",
"next-intl": "^4.8.3",
+ "next-themes": "^0.4.6",
"react": "^18",
"react-chartjs-2": "^5.3.1",
"react-dom": "^18",
diff --git a/frontend/src/app/layout.tsx b/frontend/src/app/layout.tsx
index 3d03b05..147628b 100644
--- a/frontend/src/app/layout.tsx
+++ b/frontend/src/app/layout.tsx
@@ -1,4 +1,5 @@
import type { Metadata } from "next";
+import { ThemeProvider } from "next-themes";
export const metadata: Metadata = {
title: "Stellar Guilds",
@@ -11,8 +12,18 @@ export default function RootLayout({
children: React.ReactNode;
}>) {
return (
-
-
{children}
+
+
+ {/* next-themes persists preference to localStorage under key "theme" by default */}
+
+ {children}
+
+
);
}
diff --git a/frontend/src/components/index.ts b/frontend/src/components/index.ts
index e00eac6..9e5146c 100644
--- a/frontend/src/components/index.ts
+++ b/frontend/src/components/index.ts
@@ -53,6 +53,5 @@ export { useSecurity } from '@/hooks/useSecurity'
// Stores
export { useSidebarStore } from '@/store/sidebarStore'
-export { useThemeStore } from '@/store/themeStore'
export { useWalletStore } from '@/store/walletStore'
export { useSecurityStore } from '@/store/securityStore'
\ No newline at end of file
diff --git a/frontend/src/components/layout/Header.tsx b/frontend/src/components/layout/Header.tsx
index 4e1ea81..9b32a55 100644
--- a/frontend/src/components/layout/Header.tsx
+++ b/frontend/src/components/layout/Header.tsx
@@ -7,6 +7,7 @@ import { useSidebarStore } from '@/store/sidebarStore'
import { cn } from '@/lib/utils'
import { WalletConnectButton } from '@/components/WalletConnector/WalletConnectButton'
import { WalletModal } from '@/components/WalletConnector/WalletModal'
+import { ThemeToggle } from '@/components/ui/ThemeToggle'
interface HeaderProps {
className?: string
@@ -44,6 +45,7 @@ const Header = ({ className }: HeaderProps) => {
+
diff --git a/frontend/src/components/ui/ThemeToggle.tsx b/frontend/src/components/ui/ThemeToggle.tsx
new file mode 100644
index 0000000..014d018
--- /dev/null
+++ b/frontend/src/components/ui/ThemeToggle.tsx
@@ -0,0 +1,38 @@
+'use client'
+
+import { useTheme } from 'next-themes'
+import { useEffect, useState } from 'react'
+import { Sun, Moon, Monitor } from 'lucide-react'
+
+type Theme = 'light' | 'dark' | 'system'
+
+const THEME_CYCLE: Theme[] = ['light', 'dark', 'system']
+
+const icons: Record
= {
+ light: ,
+ dark: ,
+ system: ,
+}
+
+export function ThemeToggle() {
+ const { theme, setTheme } = useTheme()
+ const [mounted, setMounted] = useState(false)
+
+ useEffect(() => setMounted(true), [])
+
+ // Render neutral placeholder until hydrated to avoid mismatch
+ if (!mounted) return
+
+ const current = (theme as Theme) ?? 'system'
+ const next = THEME_CYCLE[(THEME_CYCLE.indexOf(current) + 1) % THEME_CYCLE.length]
+
+ return (
+
+ )
+}
diff --git a/frontend/src/store/themeStore.ts b/frontend/src/store/themeStore.ts
deleted file mode 100644
index 0d9433f..0000000
--- a/frontend/src/store/themeStore.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import { create } from 'zustand'
-
-type Theme = 'light' | 'dark'
-
-interface ThemeState {
- theme: Theme
- toggleTheme: () => void
- setTheme: (theme: Theme) => void
-}
-
-export const useThemeStore = create((set) => ({
- theme: 'dark',
- toggleTheme: () => set((state) => ({
- theme: state.theme === 'light' ? 'dark' : 'light'
- })),
- setTheme: (theme) => set({ theme }),
-}))
\ No newline at end of file
diff --git a/frontend/tailwind.config.ts b/frontend/tailwind.config.ts
index 33c9f03..80f9fe0 100644
--- a/frontend/tailwind.config.ts
+++ b/frontend/tailwind.config.ts
@@ -2,6 +2,7 @@ import type { Config } from "tailwindcss";
import typography from "@tailwindcss/typography";
const config: Config = {
+ darkMode: 'class',
content: [
"./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
"./src/components/**/*.{js,ts,jsx,tsx,mdx}",