diff --git a/web/src/App.tsx b/web/src/App.tsx
index da15486b8..b688899e3 100644
--- a/web/src/App.tsx
+++ b/web/src/App.tsx
@@ -10,6 +10,7 @@ import { Routes, Route, NavLink, Navigate, useNavigate } from "react-router-dom"
import {
Activity,
BarChart3,
+ BookOpen,
Clock,
Code,
Database,
@@ -56,6 +57,9 @@ import { PluginPage, PluginSlot, usePlugins } from "@/plugins";
import type { PluginManifest } from "@/plugins";
import { useTheme } from "@/themes";
+/** Canonical public docs (Docusaurus). */
+const HERMES_DOCS_URL = "https://hermes-agent.nousresearch.com/docs/";
+
function RootRedirect() {
return ;
}
@@ -90,6 +94,13 @@ const BUILTIN_NAV: NavItem[] = [
{ path: "/skills", labelKey: "skills", label: "Skills", icon: Package },
{ path: "/config", labelKey: "config", label: "Config", icon: Settings },
{ path: "/env", labelKey: "keys", label: "Keys", icon: KeyRound },
+ {
+ path: "nav:docs",
+ labelKey: "documentation",
+ label: "Documentation",
+ icon: BookOpen,
+ href: HERMES_DOCS_URL,
+ },
];
const ICON_MAP: Record> = {
@@ -373,56 +384,88 @@ export default function App() {
aria-label={t.app.navigation}
>
- {navItems.map(({ path, label, labelKey, icon: Icon }) => (
- -
-
- cn(
- "group relative flex items-center gap-3",
- "px-5 py-2.5",
- "font-mondwest text-[0.8rem] tracking-[0.12em]",
- "whitespace-nowrap transition-colors cursor-pointer",
- "focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-midground",
- isActive
- ? "text-midground"
- : "opacity-60 hover:opacity-100",
- )
- }
- style={{
- clipPath: "var(--component-tab-clip-path)",
- }}
- >
- {({ isActive }) => (
- <>
-
-
- {labelKey
- ? ((t.app.nav as Record)[
- labelKey
- ] ?? label)
- : label}
-
+ {navItems.map(
+ ({ path, label, labelKey, href, icon: Icon }) => {
+ const navLabel = labelKey
+ ? ((t.app.nav as Record)[labelKey] ??
+ label)
+ : label;
+ return (
+
-
+ {href ? (
+
+
+ {navLabel}
-
-
- {isActive && (
- )}
- >
- )}
-
-
- ))}
+
+ ) : (
+
+ cn(
+ "group relative flex items-center gap-3",
+ "px-5 py-2.5",
+ "font-mondwest text-[0.8rem] tracking-[0.12em]",
+ "whitespace-nowrap transition-colors cursor-pointer",
+ "focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-midground",
+ isActive
+ ? "text-midground"
+ : "opacity-60 hover:opacity-100",
+ )
+ }
+ style={{
+ clipPath: "var(--component-tab-clip-path)",
+ }}
+ >
+ {({ isActive }) => (
+ <>
+
+ {navLabel}
+
+
+
+ {isActive && (
+
+ )}
+ >
+ )}
+
+ )}
+
+ );
+ },
+ )}
@@ -590,6 +633,7 @@ function SidebarSystemActions({ onNavigate }: { onNavigate: () => void }) {
}
interface NavItem {
+ href?: string;
icon: ComponentType<{ className?: string }>;
label: string;
labelKey?: string;
diff --git a/web/src/i18n/en.ts b/web/src/i18n/en.ts
index 0e7194e8a..352f6d730 100644
--- a/web/src/i18n/en.ts
+++ b/web/src/i18n/en.ts
@@ -69,12 +69,14 @@ export const en: Translations = {
analytics: "Analytics",
config: "Config",
cron: "Cron",
+ documentation: "Documentation",
keys: "Keys",
logs: "Logs",
sessions: "Sessions",
skills: "Skills",
},
navigation: "Navigation",
+ openDocumentation: "Open documentation in a new tab",
openNavigation: "Open navigation",
sessionsActiveCount: "{count} active",
statusOverview: "Status overview",
diff --git a/web/src/i18n/types.ts b/web/src/i18n/types.ts
index d13e4e7d5..45da160af 100644
--- a/web/src/i18n/types.ts
+++ b/web/src/i18n/types.ts
@@ -69,12 +69,14 @@ export interface Translations {
analytics: string;
config: string;
cron: string;
+ documentation: string;
keys: string;
logs: string;
sessions: string;
skills: string;
};
navigation: string;
+ openDocumentation: string;
openNavigation: string;
sessionsActiveCount: string;
statusOverview: string;
diff --git a/web/src/i18n/zh.ts b/web/src/i18n/zh.ts
index a57e9d69d..b7df4e24a 100644
--- a/web/src/i18n/zh.ts
+++ b/web/src/i18n/zh.ts
@@ -68,12 +68,14 @@ export const zh: Translations = {
analytics: "分析",
config: "配置",
cron: "定时任务",
+ documentation: "文档",
keys: "密钥",
logs: "日志",
sessions: "会话",
skills: "技能",
},
navigation: "导航",
+ openDocumentation: "在新标签页中打开文档",
openNavigation: "打开导航",
sessionsActiveCount: "{count} 个活跃",
statusOverview: "状态概览",