Version: v2.8.0
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.
Figure 1-1 HAMi WebUI Architecture
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