Frontend Stack
The Vulcan web frontend is built with React 19 and TypeScript, using Vite for blazing-fast development.
Core Technologies
| Technology | Version | Purpose |
|---|---|---|
| React | 19.x | Component-based UI library for building interactive user interfaces |
| TypeScript | 5.x | Static type checking and enhanced developer experience |
| Vite | 5.x | Next-generation frontend build tool with lightning-fast HMR |
UI Components
| Technology | Version | Purpose |
|---|---|---|
| MUI (Material UI) | 5.x | Comprehensive React component library implementing Material Design |
State Management
| Technology | Version | Purpose |
|---|---|---|
| TanStack Query | 5.x | Server state management, caching, and API request handling |
| Redux Toolkit | 2.x | Global client state management with simplified Redux patterns |
Routing
| Technology | Version | Purpose |
|---|---|---|
| React Router | 6.x | Declarative routing for single-page applications |
Testing
| Technology | Version | Purpose |
|---|---|---|
| Vitest | 1.x | Vite-native unit testing framework with Jest compatibility |
| React Testing Library | 16.x | Component testing utilities focused on user behavior |
| Playwright | 1.x | End-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