/** * App — routes, the shell and the theme bootstrap. * * The daemon serves the console and the API from one origin, so a real * BrowserRouter works as long as the Go handler falls back to index.html (it * does). `useThemeInit` runs the stored theme onto `` before the first * paint; `ThemeToggle` inside AppShell keeps it in sync afterwards. */ import { useEffect } from 'react' import { BrowserRouter, Route, Routes } from 'react-router-dom' import { ToastProvider } from './components/ui' import { AppShell } from './components/layout' import Blocklists from './pages/Blocklists.tsx' import Cache from './pages/Cache.tsx' import Clients from './pages/Clients.tsx' import Dashboard from './pages/Dashboard.tsx' import Domains from './pages/Domains.tsx' import Login from './pages/Login.tsx' import Logs from './pages/Logs.tsx' import LocalZones from './pages/LocalZones.tsx' import NotFound from './pages/NotFound.tsx' import Settings from './pages/Settings.tsx' import Upstreams from './pages/Upstreams.tsx' import Zones from './pages/Zones.tsx' const THEME_KEY = 'fancydns.theme' /** Applies the stored theme to `` before anything paints. */ function useThemeInit(): void { useEffect(() => { if (typeof document === 'undefined') return if (document.documentElement.dataset.theme !== undefined) return let stored: string | null = null try { stored = localStorage.getItem(THEME_KEY) } catch { // Storage disabled: fall back to the system preference. stored = null } if (stored === 'light' || stored === 'dark') { document.documentElement.dataset.theme = stored } }, []) } /** Everything that lives inside the shell. */ function AppRoutes() { return ( } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> ) } export default function App() { useThemeInit() return ( {/* Bare: no shell, no header, no nav. */} } /> } /> } /> ) }