chore: update AGENTS.md

This commit is contained in:
Melvin Ragusa
2026-01-30 05:27:45 +01:00
parent ad5ea4a3fe
commit 5a294c5182

161
AGENTS.md
View File

@@ -3,129 +3,131 @@
## Build Commands ## Build Commands
```bash ```bash
# Install dependencies
pnpm install
# Development server (port 3000) # Development server (port 3000)
npm run dev pnpm dev
# Production build # Production build
npm run build pnpm build
# Preview production build # Preview production build
npm run preview pnpm preview
``` ```
## Test Commands ## Test Commands
Use `pnpm exec` to run local binaries.
```bash ```bash
# Run all tests # Run all tests
npx vitest pnpm exec vitest
# Run tests in watch mode # Run tests in watch mode
npx vitest --watch pnpm exec vitest --watch
# Run tests with coverage # Run tests with coverage
npx vitest --coverage pnpm exec vitest --coverage
# Run a single test file # Run a single test file (Preferred method)
npx vitest src/components/ui/__tests__/Button.test.tsx pnpm exec vitest src/components/ui/__tests__/Button.test.tsx
# Run tests matching a pattern # Run tests matching a pattern
npx vitest --grep "Button" pnpm exec vitest --grep "Button"
# Run specific test by name # Run specific test by name
npx vitest -t "passes aria-label to the button element" 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 ## Code Style Guidelines
### TypeScript ### TypeScript
- Use **strict TypeScript** configuration - Use **strict TypeScript** configuration (`strict: true`).
- Always define explicit return types for functions - Always define explicit return types for functions.
- Use `type` for type definitions, `interface` for object shapes that may be extended - Use `type` for type definitions, `interface` for object shapes that may be extended.
- Avoid `any` - use `unknown` when type is uncertain - Avoid `any` - use `unknown` when type is uncertain.
- Use `import type` for type-only imports when possible.
### Imports (Order) ### Imports (Order)
1. React imports 1. React imports (`react`, `react-dom`)
2. Third-party libraries (alphabetical) 2. Third-party libraries (alphabetical, e.g., `motion/react`, `react-icons`)
3. Absolute imports from project (`@/components`, `@/utils`) 3. Absolute imports from project (`@/components`, `@/utils` if configured, otherwise relative)
4. Relative imports 4. Relative imports (`../../utils`)
5. CSS/SCSS imports last 5. CSS/SCSS imports last (`./Component.module.css`)
```typescript ```typescript
import { useState, useEffect } from 'react'; import { type ReactNode, type ButtonHTMLAttributes } from 'react';
import { motion } from 'motion/react'; import { motion } from 'motion/react';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { useTranslation } from '../../i18n';
import { debounce } from '../../utils/debounce'; import { debounce } from '../../utils/debounce';
import styles from './Navbar.module.css'; import styles from './Navbar.module.css';
``` ```
### Component Structure ### Component Structure
- Use **named exports** for all components - Use **named exports** for all components.
- Props interface should be named `[ComponentName]Props` - Props interface should be named `[ComponentName]Props`.
- Place props interface immediately before component - Place props interface immediately before component.
- Use CSS Modules for styling (`.module.css`) - Use CSS Modules for styling (`.module.css`).
- Destructure props in function signature with defaults - Use `motion` components (e.g., `motion.button`) for animations.
```typescript ```typescript
interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> { interface ButtonProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'onDrag'> {
variant?: 'primary' | 'secondary' | 'outline'; variant?: 'primary' | 'secondary' | 'outline';
size?: 'sm' | 'md' | 'lg';
isLoading?: boolean; isLoading?: boolean;
} }
export function Button({ export function Button({
variant = 'primary', variant = 'primary',
size = 'md',
isLoading = false, isLoading = false,
children, children,
className,
...props ...props
}: ButtonProps) { }: ButtonProps) {
// Implementation return (
<motion.button
className={`${styles.button} ${styles[variant]} ${className || ''}`}
whileTap={{ scale: 0.98 }}
{...props}
>
{children}
</motion.button>
);
} }
``` ```
### Naming Conventions ### Naming Conventions
- **Components**: PascalCase (e.g., `Navbar`, `Button`) - **Components**: PascalCase (e.g., `Navbar`, `Button`)
- **Hooks**: camelCase with `use` prefix (e.g., `useRateLimit`, `useTypingEffect`) - **Hooks**: camelCase with `use` prefix (e.g., `useRateLimit`)
- **Utilities**: camelCase (e.g., `debounce`, `formatDate`) - **Utilities**: camelCase (e.g., `debounce`, `formatDate`)
- **Types/Interfaces**: PascalCase (e.g., `ButtonProps`, `Translations`) - **Types/Interfaces**: PascalCase (e.g., `ButtonProps`)
- **Constants**: UPPER_SNAKE_CASE for module-level constants
- **Files**: Match default export name (e.g., `Navbar.tsx` exports `Navbar`) - **Files**: Match default export name (e.g., `Navbar.tsx` exports `Navbar`)
- **Test Files**: `[Filename].test.tsx` inside `__tests__` directory or alongside file.
### Error Handling ### Error Handling
- Use try-catch for async operations - Use try-catch for async operations.
- Provide meaningful error messages - Provide meaningful error messages.
- Use early returns to avoid nested conditionals - Clean up resources (timers, event listeners) in `useEffect` cleanup.
- 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 ### Testing
- Add `// @vitest-environment jsdom` at top of test files - Add `// @vitest-environment jsdom` at top of test files.
- Use `describe` and `it` blocks with descriptive names - Use `describe` and `it` blocks.
- Clean up after each test with `cleanup()` from testing-library - Clean up after each test with `cleanup()` from `@testing-library/react`.
- Mock external dependencies appropriately - Mock external dependencies appropriately.
- Test behavior, not implementation - Test behavior, not implementation details.
```typescript ```typescript
// @vitest-environment jsdom // @vitest-environment jsdom
@@ -133,9 +135,7 @@ import { render, screen, cleanup } from '@testing-library/react';
import { describe, it, expect, afterEach } from 'vitest'; import { describe, it, expect, afterEach } from 'vitest';
describe('Button', () => { describe('Button', () => {
afterEach(() => { afterEach(() => cleanup());
cleanup();
});
it('renders with correct aria-label', () => { it('renders with correct aria-label', () => {
render(<Button aria-label="Submit">Click</Button>); render(<Button aria-label="Submit">Click</Button>);
@@ -144,46 +144,25 @@ describe('Button', () => {
}); });
``` ```
### Performance ### Performance & Best Practices
- Use `React.lazy()` for code splitting on routes - Use `React.lazy()` for code splitting on routes.
- Memoize expensive calculations with `useMemo` - Memoize expensive calculations with `useMemo`.
- Use `requestAnimationFrame` for scroll/resize handlers - Debounce expensive operations (use `debounce` utility).
- Debounce expensive operations (use `debounce` utility) - Always include `aria-label` for interactive elements if text is not descriptive.
- Add `will-change` CSS sparingly for GPU acceleration - Ensure semantic HTML (`<nav>`, `<main>`, `<header>`).
### Accessibility
- Always include meaningful `aria-label` for interactive elements
- Use semantic HTML elements (`<header>`, `<nav>`, `<main>`)
- Ensure keyboard navigation works
- Test with screen readers
### Project Structure ### Project Structure
``` ```
src/ src/
├── components/ ├── components/
│ ├── effects/ # Visual effects (WebGL, animations) │ ├── effects/ # Visual effects
│ ├── layout/ # Layout components (Navbar, Footer) │ ├── layout/ # Layout components
│ ├── sections/ # Page sections (Hero, Services)
│ └── ui/ # Reusable UI components (Button, Input) │ └── ui/ # Reusable UI components (Button, Input)
├── hooks/ # Custom React hooks ├── hooks/ # Custom React hooks
├── i18n/ # Internationalization (de.ts, en.ts) ├── i18n/ # Internationalization
├── pages/ # Route components ├── pages/ # Route components
├── styles/ # Global styles ├── styles/ # Global styles
└── utils/ # Utility functions └── utils/ # Utility functions
``` ```
### State Management
- Use React Context for global state (e.g., i18n)
- Prefer local state when possible
- Use `useRef` for 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