import { useState, useEffect, useRef } from "react"; import { Activity, BarChart3, Clock, FileText, KeyRound, MessageSquare, Package, Settings } from "lucide-react"; import StatusPage from "@/pages/StatusPage"; import ConfigPage from "@/pages/ConfigPage"; import EnvPage from "@/pages/EnvPage"; import SessionsPage from "@/pages/SessionsPage"; import LogsPage from "@/pages/LogsPage"; import AnalyticsPage from "@/pages/AnalyticsPage"; import CronPage from "@/pages/CronPage"; import SkillsPage from "@/pages/SkillsPage"; import { LanguageSwitcher } from "@/components/LanguageSwitcher"; import { useI18n } from "@/i18n"; const NAV_ITEMS = [ { id: "status", labelKey: "status" as const, icon: Activity }, { id: "sessions", labelKey: "sessions" as const, icon: MessageSquare }, { id: "analytics", labelKey: "analytics" as const, icon: BarChart3 }, { id: "logs", labelKey: "logs" as const, icon: FileText }, { id: "cron", labelKey: "cron" as const, icon: Clock }, { id: "skills", labelKey: "skills" as const, icon: Package }, { id: "config", labelKey: "config" as const, icon: Settings }, { id: "env", labelKey: "keys" as const, icon: KeyRound }, ] as const; type PageId = (typeof NAV_ITEMS)[number]["id"]; const PAGE_COMPONENTS: Record = { status: StatusPage, sessions: SessionsPage, analytics: AnalyticsPage, logs: LogsPage, cron: CronPage, skills: SkillsPage, config: ConfigPage, env: EnvPage, }; export default function App() { const [page, setPage] = useState("status"); const [animKey, setAnimKey] = useState(0); const initialRef = useRef(true); const { t } = useI18n(); useEffect(() => { // Skip the animation key bump on initial mount to avoid re-mounting // the default page component (which causes duplicate API requests). if (initialRef.current) { initialRef.current = false; return; } setAnimKey((k) => k + 1); }, [page]); const PageComponent = PAGE_COMPONENTS[page]; return (
{/* Global grain + warm glow (matches landing page) */}
{/* ---- Header with grid-border nav ---- */}
{/* Brand — abbreviated on mobile */}
Hermes Agent
{/* Nav — icons only on mobile, icon+label on sm+ */} {/* Right side: language switcher + version badge */}
{t.app.webUi}
{/* ---- Footer ---- */}
); }