Version: v2.5.1
HAMi WebUI Developer Guide
Project positioning
HAMi WebUI is the web visualization and O&M interface of HAMi. It is mainly used to monitor, inspect, and manage nodes, GPU resources, and workloads.
The project adopts a frontend-backend separation architecture:
- Frontend (browser) is responsible for pages and interactions.
- Backend BFF is responsible for static asset hosting and API proxying.
Architecture and runtime flow
System architecture
The architecture includes frontend UI, backend services, and underlying cluster resources. Through GPU usage data collection and processing, the system provides unified visualization and analysis of resource status.
Repository structure
- Root (Node/NestJS, BFF)
- Hosts static assets from
public/ - Proxies unified
/api*requests to backend services - In development, forwards frontend page requests to the Vite dev server
- Hosts static assets from
packages/web(frontend, Vue3 + Vite)- Organizes pages, components, and routes
- Calls
/api/vgpu/*through Axios (forwarded by BFF)
server- Go backend service
Runtime ports
- BFF:
http://localhost:3000/ - Vite dev server:
http://localhost:8080/ - Backend service (proxied by BFF):
http://127.0.0.1:8000
Requests and static assets
- Frontend build output goes to root
public/(outDir: '../../public', assets inpublic/static) - BFF static hosting:
src/main.tswithapp.useStaticAssets(join(__dirname, '..', 'public')) - API proxy:
- Frontend uses
/api/vgpu/... - BFF
ApiProxyMiddlewareproxies tohttp://127.0.0.1:8000(with^/api/vgpu -> ''rewrite)
- Frontend uses
Frontend stack and module organization
Tech stack
- Vue 3 (Composition API + script setup)
- Vue Router (
packages/web/src/router/index.js, module routes inpackages/web/projects/vgpu/router.js) - Vuex (
packages/web/src/store, with global state and localStorage persistence) - i18n (
packages/web/src/locales/index.js,en.js/zh.js) - Axios (
packages/web/src/utils/request.js, unifiedcode/msg/dataerror handling) - UI libraries:
- TDesign (
packages/web/src/plugins/tdesign.js, preferred) - Element Plus (
packages/web/src/plugins/element.js)
- TDesign (
Directory conventions
- Common foundation layer (
packages/web/src/)layout/: global layout (Sidebar / TopBar / AppMain)components/: common components (BackHeader / BlockBox / Echarts-plus / Message / Confirm, etc.)hooks/: common hooks (for example,useFetchList)utils/: utility helpers (for example,request.jsand calculation helpers)icons/andcomponents/SvgIcon/: SVG icon registration and rendering
- Business module layer (
packages/web/projects/vgpu/)router.js: module routesviews/: page components (monitoring, nodes, cards, tasks, etc.)api/: API wrappers (apiPrefix = '/api/vgpu')hooks/: business hookscomponents/: business components (charts/dashboards, etc.)
Routing and menu conventions
- Route entry (
packages/web/src/router/index.js)- Mount
vgpuRoutesinconstantRouteswithLayoutas top-level layout
- Mount
- Module route (
packages/web/projects/vgpu/router.js)- Root:
/admin/vgpu - Child routes use dynamic imports
meta.titleshould be i18n keys (for example,routes.resourceAdmin,routes.nodes)
- Root:
- Menu generation (Sidebar)
- Sidebar (
packages/web/src/layout/components/Sidebar/index.vue) generates menu from current matched routes meta.titleis rendered with$t(meta.title)
- Sidebar (
- Required when adding a route/menu item:
- Add
meta.titlein routes - Add matching i18n keys in both
packages/web/src/locales/en.jsandpackages/web/src/locales/zh.js
- Add
Local development and build
One-command startup
Run from repository root:
make start-dev
This starts:
- BFF (NestJS, port 3000)
- Vite dev server (port 8080)
Coding conventions
Code style (Prettier / ESLint)
Based on repository configuration:
singleQuote: truetrailingComma: 'all'- ESLint style constraints include:
semi: 'never'quotes: ['single', ...]
Vue writing conventions
- Prefer
script setup - Do not hardcode Chinese/English strings in templates; use i18n keys
- Template:
$t('xxx.yyy') - JS/TS:
const { t } = useI18n(); t('xxx.yyy')
- Template:
- Styles usually use
scoped+lang="scss"; use:deep(...)when needed
API wrapper conventions
Under packages/web/projects/vgpu/api/:
- Use:
const apiPrefix = '/api/vgpu'- Endpoints organized as
apiPrefix + '/v1/...'
- Wrappers usually return:
request({ url, method, data/params })directly- or axios config objects, then call
request(config)in components/hooks (for example,getNodeListReq,getCardListReq,getTaskListReq)
Hooks and reuse
Prefer extracting reusable fetch/filter/pagination logic into hooks:
- Common hooks:
packages/web/src/hooks - VGPU business hooks:
packages/web/projects/vgpu/hooks
What this guide helps with
- Quickly understand how the project runs (BFF + Vite + API proxy)
- Clarify where to place code and how to connect routes/menus/i18n/API
- Reduce PR rework caused by inconsistent conventions