From 83c60ce40dc64f4707e9198d95dc166d3b3fb5de Mon Sep 17 00:00:00 2001 From: echo Date: Sun, 22 Feb 2026 00:44:46 +0100 Subject: [PATCH] ag --- AGENTS.md | 277 ++++++++++++++++++++++-------------------------------- 1 file changed, 114 insertions(+), 163 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index d5193a9..56af9f7 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,218 +1,169 @@ # Agent Guidelines for placebo.mk ## Project Overview -News site in Macedonia with sarcastic tone. Minimalistic design using TanStack stack. +Macedonian satirical news site using TanStack stack + NestJS backend. ## Tech Stack -- **Frontend**: TanStack (React 19, Query, Router) + Vite + Tailwind CSS + shadcn/ui +- **Frontend**: React 19 + TanStack (Query, Router) + Vite + Tailwind CSS + shadcn/ui - **Backend**: NestJS + TypeORM + SQLite - **CMS**: Strapi (in /cms) -## Root-Level Commands +## Commands + +### Root Level ```bash -# Docker development -npm run docker:up # Start all services -npm run docker:down # Stop all services -npm run docker:build # Rebuild containers -npm run docker:logs # View logs -npm run dev:docker # Start docker dev (alias) - -# Local development npm run dev:local # Start backend & frontend locally -npm run dev:backend:local # Backend only (local env) -npm run dev:frontend:local # Frontend only (local env) - -# Code quality +npm run dev:docker # Start via docker-compose npm run lint # Lint both projects npm run lint:fix # Auto-fix lint issues npm run type-check # Type check both projects - -# Database operations -npm run db:backup # Backup database -npm run db:restore # Restore database -npm run db:reset # Reset database - -# Environment -npm run reset:env # Reset to docker environment ``` -## Build Commands - -### Backend (NestJS) +### Backend (cd backend) ```bash -cd backend -npm install npm run start:dev # Watch mode -npm run start:debug # Debug mode -npm run build -npm run start:prod -npm run lint # Lint -npm run lint:fix # Auto-fix +npm run lint / lint:fix # ESLint npm run type-check # TypeScript check npm test # All tests -npm test:watch # Watch mode tests +npm test app.service.spec # Single file (omit .ts) +npm test -t "should return" # By pattern npm test:cov # Coverage npm test:e2e # E2E tests -npm test app.service.spec.ts # Single file -npm test -t "should return" # By test name pattern -npm run format # Format with Prettier -npm run dev:local # Local env with .env.local -npm run dev:docker # Docker env with .env.docker ``` -### Frontend (TanStack) +### Frontend (cd frontend) ```bash -cd frontend -npm install npm run dev # Vite dev server -npm run build -npm run preview -npm run lint # Lint -npm run lint:fix # Auto-fix +npm run lint / lint:fix # ESLint npm run type-check # TypeScript check npm test # All tests (Vitest) +npm test Header.test # Single file (omit .tsx) +npm test -t "renders" # By pattern npm test:ui # Vitest UI -npm test:coverage # Test coverage -npm test Header.test.tsx # Single file -npm test -t "renders" # By test name pattern -npm run dev:local # Local env with .env.local -npm run dev:docker # Docker env with .env.docker +npm test:coverage # Coverage ``` ## Code Style -### Formatting & TypeScript -- Use Prettier (2 spaces, single quotes, trailing commas, 100 char max) -- Strict TypeScript - no implicit `any`, avoid `any`, use `unknown` +### TypeScript +- Strict mode: `noImplicitAny`, `strictNullChecks`, `noFallthroughCasesInSwitch` +- No implicit `any` - use `unknown` when type uncertain - Explicit return types for public methods -- Prefer interfaces over types for objects +- Prefer `interface` over `type` for objects - Use `readonly` for immutable properties -- Backend: `noImplicitAny: true`, `strictNullChecks: true` -- Frontend: Path alias `@/*` maps to `./src/*` -### Naming Conventions -- **Files**: kebab-case (`user-profile.ts`, `auth.service.ts`) -- **Classes**: PascalCase (`UserService`, `AuthGuard`) -- **Functions/Variables**: camelCase (`getUser`, `isLoading`) -- **Constants**: UPPER_SNAKE_CASE (`MAX_RETRIES`) -- **Private members**: underscore prefix (`_cache`, `_validate()`) -- **Interfaces**: PascalCase, no 'I' prefix (`User`, `ApiResponse`) +### Formatting (Prettier) +- Single quotes, trailing commas, 2-space indent +- No semicolons in comments -### Import Order -- External libraries first, then internal modules, then relative imports -- Group imports with blank lines between groups -- Example: - ```typescript - // External - import { Module } from '@nestjs/common'; - import { TypeOrmModule } from '@nestjs/typeorm'; - - // Internal modules - import { AuthModule } from '../auth/auth.module'; - - // Relative imports - import { UserService } from './user.service'; - import { UserController } from './user.controller'; - ``` +### Naming +| Element | Convention | Example | +|---------|------------|---------| +| Files | kebab-case | `user-profile.ts`, `auth.service.ts` | +| Classes | PascalCase | `UserService`, `AuthGuard` | +| Functions/Variables | camelCase | `getUser`, `isLoading` | +| Constants | UPPER_SNAKE_CASE | `MAX_RETRIES` | +| Private members | underscore prefix | `_cache`, `_validate()` | +| Interfaces | PascalCase (no I prefix) | `User`, `ApiResponse` | +### Imports +Group with blank lines: External → Internal → Relative +```typescript +// External +import { Injectable } from '@nestjs/common'; +import { useQuery } from '@tanstack/react-query'; + +// Internal modules +import { UserService } from '../users/user.service'; + +// Relative +import { AuthResponse } from './types'; +``` ### File Structure ``` backend/src/ - modules/feature-name/ - feature-name.module.ts - feature-name.controller.ts - feature-name.service.ts - feature-name.entity.ts - feature-name.dto.ts + modules/{feature}/ + {feature}.module.ts + {feature}.controller.ts + {feature}.service.ts + {feature}.dto.ts common/{decorators,filters,guards,interceptors,pipes} - config/ + entities.ts # All TypeORM entities frontend/src/ - components/{ui,layout,features}/ - hooks/ - lib/ - queries/ - routes/ - types/ - utils/ + components/{ui,layout,features,admin,routes}/ + hooks/ # Custom React hooks + queries/ # TanStack Query hooks + lib/ # Utilities, API client + routes/ # TanStack Router routes + types/ # TypeScript types +``` + +### Path Aliases +- Frontend: `@/*` maps to `./src/*` +- Import UI components: `import { Button } from '@/components/ui/button'` + +## Patterns + +### Backend Services (NestJS) +```typescript +@Injectable() +export class AuthService { + constructor( + private userService: UserService, + private jwtService: JwtService, + ) {} + + async login(dto: LoginUserDto): Promise { + // Implementation + } +} +``` + +### Frontend Hooks (TanStack Query) +```typescript +export function useArticles(params: FindArticlesParams = {}) { + return useQuery({ + queryKey: ['articles', params], + queryFn: () => api.fetchArticles(params), + }); +} + +export function useCreateArticle() { + const queryClient = useQueryClient(); + return useMutation({ + mutationFn: api.createArticle, + onSuccess: () => queryClient.invalidateQueries({ queryKey: ['articles'] }), + }); +} ``` ### Error Handling -- **Backend**: Use NestJS exceptions (`NotFoundException`, `BadRequestException`), custom exceptions, Logger +- **Backend**: NestJS exceptions (`NotFoundException`, `BadRequestException`) - **Frontend**: Error boundaries, try-catch with user-friendly messages -### API Conventions -- REST endpoints: `/api/v1/resources` -- JSON fields: snake_case -- Pagination: `page`, `limit` query params -- Response format: - ```typescript - { - data: T, - meta: { total, page, limit }, - error?: { code, message } - } - ``` +### API Response Format +```typescript +{ data: T, meta: { total, page, limit }, error?: { code, message } } +``` -### Testing -- **Backend**: Jest with ts-jest transformer -- **Frontend**: Vitest with React Testing Library patterns -- Unit tests for services/hooks (AAA pattern: Arrange-Act-Assert) -- Integration tests for API endpoints -- E2E tests for critical user flows -- Descriptive test names that explain what is tested (e.g., `should return user data when valid ID provided`) -- Mock external dependencies (use Jest for backend, Vitest for frontend) -- Run `npm test` for all tests or target specific files/names -- Test files: `*.spec.ts` (backend), `*.test.tsx` (frontend) -- Coverage reports: `npm test:cov` (backend), `npm test:coverage` (frontend) +## Testing +- **Backend**: Jest (`*.spec.ts`), AAA pattern, mock dependencies +- **Frontend**: Vitest + React Testing Library (`*.test.tsx`) +- Descriptive names: `should return user data when valid ID provided` -### Git Workflow -- Conventional commits: `feat:`, `fix:`, `refactor:`, `test:`, `docs:`, `chore:` -- Keep commits atomic and focused -- Write clear commit messages in imperative mood +## Git Commits +- Conventional: `feat:`, `fix:`, `refactor:`, `test:`, `docs:`, `chore:` +- Atomic, imperative mood -### Component Guidelines -- Keep components small and focused (< 200 lines) -- Use functional components with hooks -- Prefer composition over inheritance -- Extract complex logic into custom hooks -- Use TanStack Query for server state management -- Use TanStack Router for routing -- Validate props with TypeScript +## UI Components +- Use shadcn/ui from `components/ui/` +- CVA for variants, clsx + tailwind-merge for classes -### Database -- Use TypeORM for SQLite -- Define entities with proper relationships -- Use migrations for schema changes -- Seed data with factory functions -- Use TypeORM repositories for data access - -### UI Components -- Use shadcn/ui components from `components/ui/` -- Use class-variance-authority (CVA) for component variants -- Use clsx and tailwind-merge for class composition -- Follow shadcn patterns for new component creation - - -## Environment Variables -- Backend: `@nestjs/config` with `.env` files -- Frontend: Vite env vars (`VITE_API_URL`) -- Never commit secrets to the repository. -- Example frontend env: `VITE_API_URL=http://localhost:3000` -- Example backend env: `DATABASE_PATH=./data.db` -- Store sensitive config in `.env` files -- Use `DATABASE_PATH` for SQLite location -- Use `@nestjs/config` for backend environment management -- Frontend env vars must be prefixed with `VITE_` - -## Agent-Specific Instructions -- **ALWAYS** run `npm run lint` and `npm run type-check` after making changes -- **NEVER** commit changes without explicit user request -- **ALWAYS** follow existing code patterns and conventions +## Agent Instructions +- **ALWAYS** run `npm run lint` and `npm run type-check` after changes +- **NEVER** commit without explicit request - **PREFER** editing existing files over creating new ones - **VERIFY** tests pass before considering work complete -- **USE** the root-level commands for common operations -- **CHECK** both backend and frontend when making API changes - - +- **CHECK** both backend/frontend when making API changes