# AGENTS.md - Coding Guidelines for RagusaIT Web ## Build Commands ```bash # Development server (port 3000) npm run dev # Production build npm run build # Preview production build npm run preview ``` ## Test Commands ```bash # Run all tests npx vitest # Run tests in watch mode npx vitest --watch # Run tests with coverage npx vitest --coverage # Run a single test file npx vitest src/components/ui/__tests__/Button.test.tsx # Run tests matching a pattern npx vitest --grep "Button" # Run specific test by name npx vitest -t "passes aria-label to the button element" ``` ## Code Style Guidelines ### TypeScript - Use **strict TypeScript** configuration - 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 ### Imports (Order) 1. React imports 2. Third-party libraries (alphabetical) 3. Absolute imports from project (`@/components`, `@/utils`) 4. Relative imports 5. CSS/SCSS imports last ```typescript import { useState, useEffect } from 'react'; import { motion } from 'motion/react'; import { Link } from 'react-router-dom'; import { useTranslation } from '../../i18n'; 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`) - Destructure props in function signature with defaults ```typescript interface ButtonProps extends ButtonHTMLAttributes { variant?: 'primary' | 'secondary' | 'outline'; size?: 'sm' | 'md' | 'lg'; isLoading?: boolean; } export function Button({ variant = 'primary', size = 'md', isLoading = false, children, ...props }: ButtonProps) { // Implementation } ``` ### Naming Conventions - **Components**: PascalCase (e.g., `Navbar`, `Button`) - **Hooks**: camelCase with `use` prefix (e.g., `useRateLimit`, `useTypingEffect`) - **Utilities**: camelCase (e.g., `debounce`, `formatDate`) - **Types/Interfaces**: PascalCase (e.g., `ButtonProps`, `Translations`) - **Constants**: UPPER_SNAKE_CASE for module-level constants - **Files**: Match default export name (e.g., `Navbar.tsx` exports `Navbar`) ### Error Handling - Use try-catch for async operations - Provide meaningful error messages - Use early returns to avoid nested conditionals - Clean up resources (timers, event listeners) in useEffect cleanup ```typescript useEffect(() => { const handleScroll = () => { if (!ticking) { window.requestAnimationFrame(() => { setIsScrolled(window.scrollY > 20); ticking = false; }); ticking = true; } }; window.addEventListener('scroll', handleScroll, { passive: true }); return () => window.removeEventListener('scroll', handleScroll); }, []); ``` ### Testing - Add `// @vitest-environment jsdom` at top of test files - Use `describe` and `it` blocks with descriptive names - Clean up after each test with `cleanup()` from testing-library - Mock external dependencies appropriately - Test behavior, not implementation ```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 - Use `React.lazy()` for code splitting on routes - Memoize expensive calculations with `useMemo` - Use `requestAnimationFrame` for scroll/resize handlers - Debounce expensive operations (use `debounce` utility) - Add `will-change` CSS sparingly for GPU acceleration ### Accessibility - Always include meaningful `aria-label` for interactive elements - Use semantic HTML elements (`
`, `