# CubeSandbox WebUI Console Architecture: React 18 SPA with TypeScript and Vite

> Explore the CubeSandbox WebUI console architecture. Discover this React 18 SPA built with Vite, featuring Radix UI, Tailwind CSS, Zustand, and React Query for efficient API integration.

- Repository: [Tencent Cloud/CubeSandbox](https://github.com/TencentCloud/CubeSandbox)
- Tags: architecture
- Published: 2026-07-10

---

**The CubeSandbox WebUI console is a React 18 single-page application built with Vite, featuring a modular component architecture powered by Radix UI primitives, Tailwind CSS styling, Zustand state management, and React Query for API integration, all accessible via port 12088.**

The TencentCloud/CubeSandbox repository delivers a modern web interface for managing sandbox environments through port 12088. The WebUI console follows a clean, component-driven architecture that separates routing, layout, state, and API concerns using industry-standard React patterns. This article examines the technical implementation details found in the `web/` directory of the repository.

## Technology Stack and Build System

The application is built as a modern **single-page application (SPA)** using **React 18** and bundled by **Vite**. The development workflow emphasizes fast hot-module replacement (HMR) and type safety through TypeScript.

The entry point resides at [`src/main.tsx`](https://github.com/TencentCloud/CubeSandbox/blob/main/src/main.tsx), where the React root mounts inside a `BrowserRouter`. Vite drives the build process through [`vite.config.ts`](https://github.com/TencentCloud/CubeSandbox/blob/main/vite.config.ts), providing fast compilation and optimized production builds. This setup ensures minimal bundle sizes and rapid development iteration when working on the CubeSandbox WebUI console.

## Layout Architecture and Routing

The core layout structure centers on the **`AppShell`** component ([`web/src/components/AppShell.tsx`](https://github.com/TencentCloud/CubeSandbox/blob/main/web/src/components/AppShell.tsx)), which composes the permanent **Rail** (sidebar navigation), **TopBar** (header with search and user actions), and a main content area.

Navigation uses **React Router v6**, with pages defined in `src/pages/*.tsx` registered implicitly through the `<Outlet/>` component within `AppShell`. The side rail handles section navigation while the top bar provides global search, language switching, and user menu access.

```tsx
import { Outlet } from 'react-router-dom';
import { Rail } from './Rail';
import { TopBar } from './TopBar';
import { CommandPalette } from './CommandPalette';
import { ToastProvider } from './ui/ToastProvider';
import { useGlobalHotkeys } from '@/hooks/useGlobalHotkeys';

function HotkeyMount() {
  useGlobalHotkeys();   // registers global shortcuts
  return null;
}

export function AppShell() {
  return (
    <div className="min-h-screen bg-background text-foreground">
      <Rail />
      <main className="ml-[68px] min-h-screen px-6 pb-10">
        <TopBar />
        <div className="mx-auto max-w-[1400px]">
          <Outlet />   {/* renders the current page */}
        </div>
      </main>
      <CommandPalette />
      <ToastProvider />
      <HotkeyMount />
    </div>
  );
}

```

## State Management with Zustand

Global UI state—including theme preferences, language settings, and authentication—lives in lightweight **Zustand** stores located at [`web/src/store/ui.ts`](https://github.com/TencentCloud/CubeSandbox/blob/main/web/src/store/ui.ts) and [`web/src/store/theme.ts`](https://github.com/TencentCloud/CubeSandbox/blob/main/web/src/store/theme.ts). These stores persist data across sessions using Zustand's middleware and are accessed via custom hooks throughout the component tree.

The theme store implementation demonstrates the pattern used across the application:

```ts
import { create } from 'zustand';
import { persist } from 'zustand/middleware';

export interface ThemeState {
  darkMode: boolean;
  toggle: () => void;
}

/* Persist theme preference across sessions */
export const useThemeStore = create<ThemeState>()(
  persist(
    (set) => ({
      darkMode: false,
      toggle: () => set((s) => ({ darkMode: !s.darkMode })),
    }),
    { name: 'theme-storage' }
  )
);

```

## UI Component System

The UI layer builds upon **Radix UI** primitives (Dialog, Tabs, Tooltip, Toast) combined with **Tailwind CSS** for styling. The project uses `tailwindcss-animate` and `tailwind-merge` for sophisticated class composition and animations.

Custom reusable components reside in `web/src/components/ui/*`, following a variant-based design system using `class-variance-authority`. The Button component illustrates this approach:

```tsx
import { VariantProps, cva } from 'class-variance-authority';
import { cn } from '@/lib/utils';

const buttonVariants = cva(
  'inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors',
  {
    variants: {
      variant: {
        default: 'bg-primary text-primary-foreground hover:bg-primary/90',
        destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90',
        outline: 'border border-input bg-background hover:bg-accent hover:text-accent-foreground',
      },
      size: {
        default: 'h-10 py-2 px-4',
        sm: 'h-9 px-3',
        lg: 'h-11 px-8',
      },
    },
    defaultVariants: {
      variant: 'default',
      size: 'default',
    },
  }
);

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

export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
  ({ className, variant, size, ...props }, ref) => (
    <button
      className={cn(buttonVariants({ variant, size, className }))}
      ref={ref}
      {...props}
    />
  )
);

```

## API Integration and Type Safety

The WebUI maintains strict type safety through auto-generated TypeScript definitions derived from the backend's OpenAPI schema. The pipeline defined in [`web/package.json`](https://github.com/TencentCloud/CubeSandbox/blob/main/web/package.json) exports the schema from the Rust backend (`cargo run --manifest-path ../CubeAPI/Cargo.toml`), then generates types using `openapi-typescript`.

```json
// package.json scripts
{
  "scripts": {
    "api:export": "cargo run --manifest-path ../CubeAPI/Cargo.toml -- --export-openapi ../openapi.yml",
    "api:generate": "openapi-typescript ../openapi.yml -o src/api/generated/schema.ts",
    "api:sync": "npm run api:export && npm run api:generate"
  }
}

```

Running `npm run api:sync` updates the TypeScript definitions at [`web/src/api/generated/schema.ts`](https://github.com/TencentCloud/CubeSandbox/blob/main/web/src/api/generated/schema.ts). The application uses **React Query** (`@tanstack/react-query`) for data fetching, caching, and synchronization, consuming these generated types for end-to-end type safety.

## Developer Experience Features

The console includes several ergonomic features for power users. **Global hotkeys** are registered in [`web/src/hooks/useGlobalHotkeys.ts`](https://github.com/TencentCloud/CubeSandbox/blob/main/web/src/hooks/useGlobalHotkeys.ts) and exposed through the `<CommandPalette/>` component ([`web/src/components/CommandPalette.tsx`](https://github.com/TencentCloud/CubeSandbox/blob/main/web/src/components/CommandPalette.tsx)), enabling keyboard-driven navigation and actions.

**Internationalization** uses **i18next** with browser language detection, storing locale JSON files in `web/src/locales/{en,zh}`. The **ThemeProvider** ([`web/src/components/ThemeProvider.tsx`](https://github.com/TencentCloud/CubeSandbox/blob/main/web/src/components/ThemeProvider.tsx)) manages light/dark mode toggling via CSS variables, accessible through the `ThemeToggle` component.

## Summary

- **CubeSandbox WebUI console** is a React 18 SPA built with Vite and TypeScript, served on port 12088.
- **Layout architecture** centers on [`AppShell.tsx`](https://github.com/TencentCloud/CubeSandbox/blob/main/AppShell.tsx), combining `Rail`, `TopBar`, and React Router v6's `<Outlet/>` for navigation.
- **State management** uses Zustand for lightweight, persistent global stores located in `web/src/store/`.
- **UI components** are built on Radix UI primitives with Tailwind CSS styling, organized in `web/src/components/ui/`.
- **API layer** generates TypeScript types from OpenAPI schemas using `openapi-typescript`, consumed by React Query for type-safe data fetching.

## Frequently Asked Questions

### What frontend framework powers the CubeSandbox WebUI console?

The console is built as a **React 18** single-page application using **Vite** as the build tool. It uses **TypeScript** throughout for type safety and **React Router v6** for client-side navigation.

### How does the WebUI console handle API type safety?

The project auto-generates TypeScript definitions from the backend's OpenAPI specification using `openapi-typescript`. The generated types live in [`web/src/api/generated/schema.ts`](https://github.com/TencentCloud/CubeSandbox/blob/main/web/src/api/generated/schema.ts) and are used with **React Query** to ensure end-to-end type safety between the frontend and backend APIs.

### Where is global state managed in the CubeSandbox WebUI?

Global state—including theme preferences and UI settings—is managed by **Zustand** stores in [`web/src/store/ui.ts`](https://github.com/TencentCloud/CubeSandbox/blob/main/web/src/store/ui.ts) and [`web/src/store/theme.ts`](https://github.com/TencentCloud/CubeSandbox/blob/main/web/src/store/theme.ts). These stores use persistence middleware to maintain user preferences across browser sessions.

### How are UI components styled consistently across the console?

The UI uses **Radix UI** primitives for accessibility and behavior, styled with **Tailwind CSS** utilities. Components follow a variant-based system using `class-variance-authority` (as seen in [`web/src/components/ui/button.tsx`](https://github.com/TencentCloud/CubeSandbox/blob/main/web/src/components/ui/button.tsx)), ensuring consistent theming and design patterns throughout the application.