5.0 KiB
5.0 KiB
AGENTS.md - Coding Guidelines for RagusaIT Web
Build Commands
# Development server (port 3000)
npm run dev
# Production build
npm run build
# Preview production build
npm run preview
Test Commands
# 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
typefor type definitions,interfacefor object shapes that may be extended - Avoid
any- useunknownwhen type is uncertain
Imports (Order)
- React imports
- Third-party libraries (alphabetical)
- Absolute imports from project (
@/components,@/utils) - Relative imports
- CSS/SCSS imports last
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
interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
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
useprefix (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.tsxexportsNavbar)
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
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 jsdomat top of test files - Use
describeanditblocks with descriptive names - Clean up after each test with
cleanup()from testing-library - Mock external dependencies appropriately
- Test behavior, not implementation
// @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(<Button aria-label="Submit">Click</Button>);
expect(screen.getByRole('button', { name: /submit/i })).toBeTruthy();
});
});
Performance
- Use
React.lazy()for code splitting on routes - Memoize expensive calculations with
useMemo - Use
requestAnimationFramefor scroll/resize handlers - Debounce expensive operations (use
debounceutility) - Add
will-changeCSS sparingly for GPU acceleration
Accessibility
- Always include meaningful
aria-labelfor interactive elements - Use semantic HTML elements (
<header>,<nav>,<main>) - Ensure keyboard navigation works
- Test with screen readers
Project Structure
src/
├── components/
│ ├── effects/ # Visual effects (WebGL, animations)
│ ├── layout/ # Layout components (Navbar, Footer)
│ ├── sections/ # Page sections (Hero, Services)
│ └── ui/ # Reusable UI components (Button, Input)
├── hooks/ # Custom React hooks
├── i18n/ # Internationalization (de.ts, en.ts)
├── pages/ # Route components
├── styles/ # Global styles
└── utils/ # Utility functions
State Management
- Use React Context for global state (e.g., i18n)
- Prefer local state when possible
- Use
useReffor DOM references and mutable values - Store user preferences in localStorage with proper keys
Comments
- Use JSDoc for exported functions
- Explain "why" not "what" in comments
- Keep comments concise and meaningful