# AGENTS.md - Coding Guidelines for RagusaIT Web ## Build Commands ```bash # Install dependencies pnpm install # Development server (port 3000) pnpm dev # Production build pnpm build # Preview production build pnpm preview ``` ## Test Commands Use `pnpm exec` to run local binaries. ```bash # Run all tests pnpm exec vitest # Run tests in watch mode pnpm exec vitest --watch # Run tests with coverage pnpm exec vitest --coverage # Run a single test file (Preferred method) pnpm exec vitest src/components/ui/__tests__/Button.test.tsx # Run tests matching a pattern pnpm exec vitest --grep "Button" # Run specific test by name pnpm exec vitest -t "passes aria-label to the button element" ``` ## Lint & Type Check ```bash # Type check (strict) pnpm exec tsc --noEmit ``` ## Code Style Guidelines ### TypeScript - Use **strict TypeScript** configuration (`strict: true`). - Always define explicit return types for functions. - Use `type` for type definitions, `interface` for object shapes that may be extended. - Avoid `any` - use `unknown` when type is uncertain. - Use `import type` for type-only imports when possible. ### Imports (Order) 1. React imports (`react`, `react-dom`) 2. Third-party libraries (alphabetical, e.g., `motion/react`, `react-icons`) 3. Absolute imports from project (`@/components`, `@/utils` if configured, otherwise relative) 4. Relative imports (`../../utils`) 5. CSS/SCSS imports last (`./Component.module.css`) ```typescript import { type ReactNode, type ButtonHTMLAttributes } from 'react'; import { motion } from 'motion/react'; import { Link } from 'react-router-dom'; import { debounce } from '../../utils/debounce'; import styles from './Navbar.module.css'; ``` ### Component Structure - Use **named exports** for all components. - Props interface should be named `[ComponentName]Props`. - Place props interface immediately before component. - Use CSS Modules for styling (`.module.css`). - Use `motion` components (e.g., `motion.button`) for animations. ```typescript interface ButtonProps extends Omit, 'onDrag'> { variant?: 'primary' | 'secondary' | 'outline'; isLoading?: boolean; } export function Button({ variant = 'primary', isLoading = false, children, className, ...props }: ButtonProps) { return ( {children} ); } ``` ### Naming Conventions - **Components**: PascalCase (e.g., `Navbar`, `Button`) - **Hooks**: camelCase with `use` prefix (e.g., `useRateLimit`) - **Utilities**: camelCase (e.g., `debounce`, `formatDate`) - **Types/Interfaces**: PascalCase (e.g., `ButtonProps`) - **Files**: Match default export name (e.g., `Navbar.tsx` exports `Navbar`) - **Test Files**: `[Filename].test.tsx` inside `__tests__` directory or alongside file. ### Error Handling - Use try-catch for async operations. - Provide meaningful error messages. - Clean up resources (timers, event listeners) in `useEffect` cleanup. ### Testing - Add `// @vitest-environment jsdom` at top of test files. - Use `describe` and `it` blocks. - Clean up after each test with `cleanup()` from `@testing-library/react`. - Mock external dependencies appropriately. - Test behavior, not implementation details. ```typescript // @vitest-environment jsdom import { render, screen, cleanup } from '@testing-library/react'; import { describe, it, expect, afterEach } from 'vitest'; describe('Button', () => { afterEach(() => cleanup()); it('renders with correct aria-label', () => { render(); expect(screen.getByRole('button', { name: /submit/i })).toBeTruthy(); }); }); ``` ### Performance & Best Practices - Use `React.lazy()` for code splitting on routes. - Memoize expensive calculations with `useMemo`. - Debounce expensive operations (use `debounce` utility). - Always include `aria-label` for interactive elements if text is not descriptive. - Ensure semantic HTML (`