# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview **GPUStack UI** — Dashboard/management UI for [GPUStack](https://github.com/gpustack/gpustack), a GPU model serving and management platform. Features include model deployment, playground (chat/embedding/rerank/image/speech), resource management, cluster management, benchmark, and access control. ## Tech Stack - **Framework**: UmiJS Max 4.x (`@umijs/max`) — enterprise React framework with built-in routing, state, request, access, locale, and layout plugins - **UI Library**: Ant Design 6.x (`antd`) + Pro Components (`@ant-design/pro-components`) - **Core UI package**: `@gpustack/core-ui` — shared internal UI components - **State Management**: Jotai (atomic state via `src/atoms/`) - **HTTP Client**: Axios via Umi request layer - **Build Tool**: Webpack (via Umi) - **Language**: TypeScript - **Package Manager**: pnpm - **Styling**: Less + CSS modules + styled-components + antd-style ## Key Commands ```bash # Install dependencies pnpm install # Start dev server (http://localhost:9000) npm run dev # or: pnpm dev # Production build npm run build # Preview build output npm run preview # Format code npm run format # Check locale files npm run check:locales ``` Environment variables: - `PROXY_HOST` — API proxy target for dev server - `ENABLE_ENTERPRISE` — enable enterprise features - `ENABLE_PLAYGROUND` — enable playground section (default: true) - `APP_TITLE` — custom app title ## Project Structure ``` config/ # Umi build configuration config.ts # Main config (proxy, build, plugins, routes) routes.ts # Route definitions (main entry for navigation structure) routes.extensions.ts # Build-time route extensions proxy.ts # Dev proxy configuration plugins.ts # Webpack plugins (compression, monaco) keep-alive.ts # Route keep-alive configuration mfsu.extensions.ts # MFSU exclusions src/ app.tsx # App entry: getInitialState, request config, plugin initialization access.ts # Role-based access control (canSeeAdmin, canSeeOrgAdmin, etc.) request-config.tsx # Axios interceptors, error handling, 401 redirect global.tsx # Global setup (dayjs plugins) global.less # Global styles atoms/ # Jotai atomic state (user, settings, models, clusters, etc.) config/ # Runtime config (settings, theme, hotkeys, breakpoints) layouts/ # Custom layout system (sidebar, menu, logo, error boundary) pages/ # Page components (feature-based subdirectories) _components/ # Shared page-level components dashboard/ # Dashboard playground/ # Chat, embedding, rerank, images, speech llmodels/ # Model catalog, user models, deployments model-routes/ # Model routing usage/ # Usage statistics maas-provider/ # Model providers benchmark/ # Benchmark tests gpu-service/ # GPU service (instances, templates, storage, public keys) resources/ # Workers, GPUs, backends, modelfiles cluster-management/ # Clusters, credentials users/ # User management api-keys/ # API key management login/ # Login page profile/ # User profile components/ # Global shared components plugins/ # Plugin system (manager, enterprise-ready, locale merger) services/ # API service layer (minimal, most API calls are inline) locales/ # i18n locale files assets/ # Images, logos, provider logos request.extensions.ts # Build-time request interceptor hooks (empty by default) access.extensions.ts # Build-time access extension hooks (empty by default) ``` ## Architecture Patterns ### Routing - Hash-based routing (`history.type: 'hash'`) - Routes defined in `config/routes.ts` with icon, access control, and keep-alive support - Route extensions applied via `config/routes.extensions.ts` for build-time plugin injection ### Authentication & Access Control - Umi `access` plugin with predicate-based role checks - Key predicates: `canSeeAdmin`, `canSeeOrgAdmin`, `canManageCurrentOrg`, `canSeeUser`, `canDelete`, `canLogin` - 401 responses trigger logout → redirect to `/login` - First-login flow redirects admin to `/resources/workers` ### State Management - **Jotai atoms** in `src/atoms/` for global state (user info, settings, pagination, route cache, etc.) - **Umi `initialState`** for currentUser and fetchUserInfo - Persistent storage via `setAtomStorage` / `clearAtomStorage` utilities ### HTTP Requests - Base URL: `/v2` (GPUSTACK_API_BASE_URL) - OpenAI-compatible APIs: `/v1` - Special paths (`/auth`, `/v1`, `/version`, `/proxy`, `/update`) bypass the API base URL - Request/response interceptors in `src/request-config.tsx` - Extension point: `src/request.extensions.ts` (empty by default, populated by build-time tooling) ### Plugin System - `GPUStackPluginManager` in `src/plugins/manager.ts` - Plugins register with `onAppInit` and `onAppReady` lifecycle hooks - Enterprise plugin loaded via `src/plugins/enterprise-ready.ts` - Build-time extensions populate `*.extensions.ts` files ### Layout - Custom layout in `src/layouts/` with sidebar, menu, logo, right panel - Error boundary and exception pages - Render links and extra render hooks for plugin injection ### Internationalization - Umi locale plugin with `en-US` default - Ant Design locale auto-synced - Locale files in `src/locales/` ## Important Notes - The `.extensions.ts` files (`routes.extensions.ts`, `request.extensions.ts`, `access.extensions.ts`, etc.) are **generated at build time** by external tooling — do not edit them directly - Monaco Editor is integrated via `@monaco-editor/react` and `monaco-editor-webpack-plugin` - XTerm.js used for terminal/console output - Markdown rendering with `react-markdown` + GFM + KaTeX math support - The project uses hash routing, so all routes have `#/` prefix in the browser