--- name: xray-ui-dev description: Development and maintenance of Xray Config UI Editor. Use this skill when modifying the React frontend, Zustand store, Xray-core configuration logic, or Remnawave integration. --- # Xray UI Dev This skill provides specialized knowledge for developing the Xray Config UI Editor, a static web-based GUI for Xray-core. ## Tech Stack & Workflow - **Runtime**: Bun (use `bun install`, `bun run dev`, `bun run build`) - **Frontend**: React 19 (TypeScript), Vite 7 - **Styling**: Tailwind CSS 4 - **State Management**: Zustand 5 + Immer (see `src/store/configStore.ts`) - **Icons**: Phosphor Icons (`@phosphor-icons/react`) - **Visuals**: React Flow (`@xyflow/react`) for topology visualization - **Editor**: CodeMirror 6 (`@codemirror/*`, `@platformos/lang-jsonc`) for JSON/JSONC editing — not Monaco. ## State Management (Zustand) The application state is managed in `src/store/configStore.ts`. - Use `useConfigStore` to access the Xray configuration and Remnawave state. - Most CRUD actions go through the `resolveMutableConfig` helper (parses `rawConfigText`, falls back to `config`) rather than `produce` directly — see that file's actions for the pattern. - Configuration is persisted in IndexedDB (`src/utils/indexedDbStorage.ts`) under the `xray-config-storage` key, with a one-time migration from legacy `localStorage`. The store exposes `hasHydrated`/`setHasHydrated` — gate any code that reads/writes the store on mount behind `hasHydrated` (see `App.tsx`), since the IndexedDB read is async. ### Common Actions - `updateSection(section, data)`: Replaces a top-level Xray config section. - `addItem(section, item)`: Adds an inbound or outbound. - `updateItem(section, index, item)`: Updates a specific item in a list. - `saveToRemnawave()`: Pushes the current config to the linked Remnawave profile. ## Xray Configuration Logic - **Schema**: The hand-authored source of truth is Zod, in `src/core/xray/schemas/**`. A separate JSON Schema (`src/utils/config.schema.json`, auto-generated by `bun run schema:generate` from Xray-core's Go sources) backs the raw-JSON editor's Ajv linter — the two can drift, see the plan doc / recent commits before assuming they agree. - **Validation**: `src/core/validators/index.ts` (Zod-based; `validateFullConfig` covers the whole config) and `src/core/diagnostics/index.ts` (`runFullDiagnostics`, semantic checks like dangling routing targets). `saveToRemnawave()` and `saveActiveProfile()` in `configStore.ts` both gate on `runFullDiagnostics` critical findings. - **Protocols**: Supports VMess, VLESS, Trojan, Shadowsocks, Hysteria2, Wireguard, etc. ## UI Components - **Modals**: Most editing happens in modals located in `src/components/editors/`. - **UI Elements**: Reusable components are in `src/components/ui/` (Button, Icon, Modal, etc.). - **Topology**: Traffic flow visualization is in `src/components/topology/`. ## Key Files to Reference - `src/store/configStore.ts`: Central state and logic. - `src/utils/config.schema.json`: Auto-generated JSON Schema for the raw-JSON editor's linter (see `scripts/generate-xray-schema.cjs`). - `src/core/api/remnawave-client.ts`: API client for Remnawave integration. - `src/core/validators/index.ts`: Zod-based configuration validation logic. - `src/core/diagnostics/index.ts`: Semantic diagnostics (dangling tags, incompatible flags) that gate save/push. ## Best Practices 1. **Type Safety**: Always maintain strict TypeScript types for Xray config objects. 2. **Immutability**: Use `produce` from `immer` when updating the store to avoid direct state mutation. 3. **Validation**: Add validation logic for new config sections to prevent Xray-core from crashing. 4. **Tailwind 4**: Use modern Tailwind 4 features for styling.