Files
dashboard/AGENTS.md
sakuradairong dc9c9d9735 fix(i18n): localize RouteModal, SetupKeyModal, CreateAccessTokenModal
- RouteModal: routeType, networkRange, domains, distributionGroups, metric
- SetupKeyModal: createTitle, nameHelp, usageLimitHelp, expiresIn
- CreateAccessTokenModal: tokenName, tokenNameHelp, tokenExpiresIn
- Add corresponding keys to en.ts and zh.ts
2026-06-23 21:38:18 +08:00

10 KiB
Raw Permalink Blame History

仓库指南

项目概述

NetBird Dashboard 是 NetBird 管理服务的 Web 界面。这是一个 Next.js 应用程序,为 NetBird 网络提供网络管理、对等节点监控、访问控制和配置功能。

在线版本: https://app.netbird.io/ 源代码: https://github.com/netbirdio/dashboard

架构与数据流

技术栈

  • 框架: Next.js 13+ 使用 App Router
  • 语言: TypeScript
  • 样式: Tailwind CSS + shadcn/ui 组件
  • 状态管理: React Context + SWR 用于服务器状态
  • 认证: OIDC 通过 @axa-fr/react-oidc
  • 国际化: next-intl
  • 测试: Cypress (E2E)
  • 部署: Docker + Nginx

高级结构

src/
├── app/                    # Next.js App Router 页面
│   ├── (dashboard)/        # 主仪表板路由(分组布局)
│   ├── (remote-access)/    # 远程访问路由
│   ├── install/            # 安装向导
│   ├── invite/             # 用户邀请流程
│   └── setup/              # 初始设置流程
├── assets/                 # 静态资源(图标、图片、字体)
├── auth/                   # OIDC 认证组件
├── components/             # 共享 UI 组件(基于 shadcn/ui
├── contexts/               # React Context 提供者
├── hooks/                  # 自定义 React 钩子
├── i18n/                   # 国际化配置和消息
├── interfaces/             # TypeScript 类型定义
├── layouts/                # 布局组件
├── modules/                # 功能模块(领域特定)
└── utils/                  # 工具函数

数据流

  1. 认证: OIDC 提供者处理认证 → 令牌存储在内存中
  2. API 调用: useFetchApi 钩子 → SWR → OIDC 请求 → 管理 API
  3. 状态: 服务器状态通过 SWR 缓存UI 状态通过 React Context
  4. 渲染: 默认使用服务器组件,需要时使用客户端组件

关键目录

src/app/ - 页面和路由

  • 使用 Next.js App Router 和路由分组
  • (dashboard)/ 包含主要应用页面和共享布局
  • 每个路由有 page.tsx 和可选的 layout.tsx
  • 通过 error/page.tsx 实现错误边界

src/modules/ - 功能模块

按功能组织的领域特定组件:

  • peers/ - 对等节点管理组件
  • networks/ - 网络配置
  • access-control/ - ACL 策略
  • dns/ - DNS 管理
  • routes/ - 网络路由
  • users/ - 用户管理
  • groups/ - 分组管理
  • setup-keys/ - 设置密钥管理
  • activity/ - 活动日志
  • settings/ - 账户设置

src/components/ - 共享 UI 组件

基于 shadcn/ui 构建,具有自定义变体:

  • Input.tsx - 带验证的表单输入
  • Select.tsx - 下拉选择
  • Dialog.tsx - 模态对话框
  • Table.tsx - 数据表格
  • Button.tsx - 操作按钮
  • Badge.tsx - 状态徽章
  • Tooltip.tsx - 信息提示

src/contexts/ - 状态提供者

全局状态的 React Context 提供者:

  • ApplicationProvider.tsx - 应用级配置
  • PeersProvider.tsx - 对等节点数据
  • GroupsProvider.tsx - 分组数据
  • RoutesProvider.tsx - 路由数据
  • PoliciesProvider.tsx - ACL 策略
  • PermissionsProvider.tsx - 用户权限
  • GlobalThemeProvider.tsx - 主题管理
  • LocaleProvider.tsx - 语言/区域设置

src/hooks/ - 自定义钩子

可复用的 React 钩子:

  • useLocalStorage.tsx - 持久化本地存储
  • useDebounce.tsx - 防抖值
  • useSearch.ts - 搜索功能
  • useCopyToClipboard.ts - 剪贴板操作
  • useElementSize.ts - DOM 元素尺寸
  • useIntersectionObserver.ts - 可见性检测

src/interfaces/ - 类型定义

领域模型的 TypeScript 接口:

  • Peer.ts - 网络对等节点
  • Group.ts - 对等节点分组
  • Route.ts - 网络路由
  • Nameserver.ts - DNS 名称服务器
  • Account.ts - 用户账户
  • SetupKey.ts - 设置密钥
  • AccessToken.ts - API 访问令牌

src/utils/ - 工具函数

辅助函数:

  • api.tsx - 集成 SWR 的 API 客户端
  • helpers.ts - 通用工具cn, randomString 等)
  • config.ts - 配置加载器
  • ip.ts - IP 地址工具
  • wireguard.ts - WireGuard 辅助函数
  • version.ts - 版本比较

开发命令

# 安装依赖
npm install

# 启动开发服务器(端口 3000
npm run dev

# 使用 Turbopack 启动(更快)
npm run turbo

# 构建生产版本
npm run build

# 启动生产服务器
npm start

# 运行代码检查
npm run lint

# 打开 Cypress 测试运行器
npm run cypress:open

# 复制 OIDC 服务工作者(认证必需)
npm run copy
npm run copytrusted

代码规范和常见模式

组件模式

// 使用 shadcn/ui 和 class-variance-authority 实现变体
import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "@utils/helpers";

const buttonVariants = cva("base-classes", {
  variants: {
    variant: {
      default: "default-classes",
      destructive: "destructive-classes",
    },
  },
});

interface ButtonProps
  extends React.ButtonHTMLAttributes<HTMLButtonElement>,
    VariantProps<typeof buttonVariants> {}

export function Button({ className, variant, ...props }: ButtonProps) {
  return (
    <button
      className={cn(buttonVariants({ variant }), className)}
      {...props}
    />
  );
}

Context 提供者模式

import React, { useMemo } from "react";
import useFetchApi from "@utils/api";

const DataContext = React.createContext({} as DataType);

export default function DataProvider({ children }: { children: React.ReactNode }) {
  const { data, isLoading } = useFetchApi<Data[]>("/endpoint");

  const value = useMemo(() => ({ data, isLoading }), [data, isLoading]);

  return (
    <DataContext.Provider value={value}>
      {children}
    </DataContext.Provider>
  );
}

export const useData = () => React.useContext(DataContext);

API 钩子模式

import useFetchApi from "@utils/api";

// GET 请求使用 SWR
const { data, isLoading, error } = useFetchApi<Data[]>("/endpoint");

// POST/PUT/DELETE 请求
const { mutate } = useFetchApi("/endpoint", { method: "POST" });

样式模式

import { cn } from "@utils/helpers";

// 合并 Tailwind 类
<div className={cn(
  "base-classes",
  condition && "conditional-classes",
  className
)} />

导入顺序

simple-import-sort ESLint 插件强制执行:

  1. 副作用导入 (import "polyfill")
  2. 外部包 (import React from "react")
  3. 内部别名 (import { Button } from "@/components")
  4. 相对导入 (import { useData } from "./context")

文件命名

  • 组件: PascalCase (PeerTable.tsx, GroupSelector.tsx)
  • 钩子: camelCase 带 use 前缀 (useLocalStorage.tsx)
  • 工具函数: camelCase (helpers.ts, api.tsx)
  • 接口: PascalCase (Peer.ts, Group.ts)
  • 页面: page.tsxNext.js App Router 要求)
  • 布局: layout.tsxNext.js App Router 要求)

重要文件

入口点

  • src/app/layout.tsx - 根布局(提供者、字体、元数据)
  • src/app/(dashboard)/layout.tsx - 仪表板布局(导航、认证)
  • src/app/page.tsx - 首页重定向

配置文件

  • next.config.js - Next.js 配置
  • tailwind.config.ts - Tailwind CSS 配置
  • components.json - shadcn/ui 配置
  • config.json - 应用配置API 端点、认证)
  • .eslintrc.json - ESLint 规则
  • tsconfig.json - TypeScript 配置

关键工具

  • src/utils/api.tsx - API 客户端SWR + OIDC
  • src/utils/config.ts - 配置加载器
  • src/utils/helpers.ts - 共享工具
  • src/auth/OIDCProvider.tsx - 认证提供者

运行时/工具偏好

必需环境

  • Node.js 18+(推荐 LTS
  • npm包管理器

本地开发设置

  1. 克隆仓库
  2. 创建 .local-config.json 覆盖 config.json 中的值
  3. 运行 npm install
  4. 运行 npm run copy(复制 OIDC 服务工作者)
  5. 运行 npm run dev

Docker 部署

docker run -d --name netbird-dashboard \
  -p 80:80 \
  -e AUTH0_DOMAIN=<domain> \
  -e AUTH0_CLIENT_ID=<client-id> \
  -e AUTH0_AUDIENCE=<audience> \
  -e NETBIRD_MGMT_API_ENDPOINT=<api-url> \
  netbirdio/dashboard:main

配置

  • config.json - 默认配置
  • .local-config.json - 本地覆盖(已忽略)
  • Docker 部署的环境变量

测试与质量保证

E2E 测试Cypress

# 打开 Cypress UI
npm run cypress:open

# 无头运行测试
npx cypress run

测试位置: cypress/e2e/ 支持文件: cypress/support/ 测试数据: cypress/fixtures/

代码检查

npm run lint

ESLint 配置:

  • next/core-web-vitals - Next.js 最佳实践
  • prettier - 代码格式化
  • simple-import-sort - 导入排序

类型检查

TypeScript 严格模式已启用。运行 npx tsc --noEmit 检查类型。

模块上下文

参见 docs/contexts/ 获取特定模块的详细文档:

  • peers.md - 对等节点管理模块
  • networks.md - 网络配置模块
  • access-control.md - ACL 策略模块
  • dns.md - DNS 管理模块
  • api-client.md - API 客户端模式
  • authentication.md - OIDC 认证流程

常见问题与注意事项

OIDC 服务工作者

安装后必须运行 npm run copy 将 OIDC 服务工作者复制到 public/

本地配置

创建 .local-config.json 覆盖 config.json 中的本地开发值。

静态导出

应用在 Next.js 配置中使用 output: "export" - 运行时无服务器端渲染。

暗黑模式

主题通过 GlobalThemeProvider 管理。使用 Tailwind 暗黑模式类。

API 端点

所有 API 调用通过 src/utils/api.tsx,它处理:

  • OIDC 令牌注入
  • 令牌刷新
  • 错误处理
  • SWR 缓存

快速参考

添加新页面

  1. 创建 src/app/(dashboard)/new-page/page.tsx
  2. src/layouts/Navigation.tsx 中添加导航
  3. 如需要,在 src/contexts/ 中创建上下文提供者
  4. src/interfaces/ 中添加类型

添加新组件

  1. src/components/(共享)或 src/modules/<feature>/(功能特定)中创建
  2. 遵循 shadcn/ui 模式并实现变体
  3. 从组件文件导出

添加新 API 端点

  1. 在组件或上下文中使用 useFetchApi 钩子
  2. src/interfaces/ 中添加 TypeScript 接口
  3. 如果数据在组件间共享,创建上下文提供者

添加新模块

  1. src/modules/<feature>/ 中创建目录
  2. 为该功能添加组件
  3. src/contexts/ 中创建上下文提供者
  4. src/app/(dashboard)/<feature>/ 中添加页面
  5. 更新导航

本文档由 AI 自动生成。随着代码库的发展而更新。