Skip to content

Frontend Stack

The Vulcan web frontend is built with React 19 and TypeScript, using Vite for blazing-fast development.

Core Technologies

TechnologyVersionPurpose
React19.xComponent-based UI library for building interactive user interfaces
TypeScript5.xStatic type checking and enhanced developer experience
Vite5.xNext-generation frontend build tool with lightning-fast HMR

UI Components

TechnologyVersionPurpose
MUI (Material UI)5.xComprehensive React component library implementing Material Design

State Management

TechnologyVersionPurpose
TanStack Query5.xServer state management, caching, and API request handling
Redux Toolkit2.xGlobal client state management with simplified Redux patterns

Routing

TechnologyVersionPurpose
React Router6.xDeclarative routing for single-page applications

Testing

TechnologyVersionPurpose
Vitest1.xVite-native unit testing framework with Jest compatibility
React Testing Library16.xComponent testing utilities focused on user behavior
Playwright1.xEnd-to-end testing framework for modern web apps

State Management Strategy

Server State (TanStack Query)

Use TanStack Query for all data that comes from the server:

  • API responses
  • Cached data
  • Loading and error states
  • Automatic refetching
typescript
const { data, isLoading, error } = useQuery({
  queryKey: ['leads'],
  queryFn: () => leadsApi.getAll(),
});

Client State (Redux Toolkit)

Use Redux for UI state that doesn't come from the server:

  • Sidebar open/closed
  • Theme preference
  • Modal states
  • Form wizard steps
typescript
const dispatch = useDispatch();
dispatch(toggleSidebar());

Component Patterns

Props Interface Pattern

typescript
interface LeadCardProps {
  lead: Lead;
  onEdit: (id: string) => void;
  onDelete: (id: string) => void;
}

export function LeadCard({ lead, onEdit, onDelete }: LeadCardProps) {
  // Component implementation
}

Hooks First Pattern

typescript
export function LeadDetail({ id }: { id: string }) {
  // 1. Hooks at the top
  const { data: lead, isLoading } = useLead(id);
  const { mutate: deleteLead } = useDeleteLead();

  // 2. Early returns for loading/error
  if (isLoading) return <LoadingSpinner />;
  if (!lead) return <NotFound />;

  // 3. Main render
  return <Paper>{/* ... */}</Paper>;
}

Build Commands

bash
npm run dev             # Start development server
npm run build           # Production build
npm run preview         # Preview production build
npm run lint            # Run ESLint
npm run type-check      # TypeScript type checking
npm run test            # Run unit tests
npm run test:e2e        # Run E2E tests
npm run generate:client # Generate API client from OpenAPI spec

Built with VitePress | v1.1.0