4.9 KiB
4.9 KiB
Agent Guidelines for placebo.mk
Project Overview
Macedonian satirical news site using TanStack stack + NestJS backend.
Tech Stack
- Frontend: React 19 + TanStack (Query, Router) + Vite + Tailwind CSS + shadcn/ui
- Backend: NestJS + TypeORM + SQLite
- CMS: Strapi (in /cms)
Commands
Root Level
npm run dev:local # Start backend & frontend locally
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
Backend (cd backend)
npm run start:dev # Watch mode
npm run lint / lint:fix # ESLint
npm run type-check # TypeScript check
npm test # All 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
Frontend (cd frontend)
npm run dev # Vite dev server
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 # Coverage
Code Style
TypeScript
- Strict mode:
noImplicitAny,strictNullChecks,noFallthroughCasesInSwitch - No implicit
any- useunknownwhen type uncertain - Explicit return types for public methods
- Prefer
interfaceovertypefor objects - Use
readonlyfor immutable properties
Formatting (Prettier)
- Single quotes, trailing commas, 2-space indent
- No semicolons in comments
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
// 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}/
{feature}.module.ts
{feature}.controller.ts
{feature}.service.ts
{feature}.dto.ts
common/{decorators,filters,guards,interceptors,pipes}
entities.ts # All TypeORM entities
frontend/src/
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)
@Injectable()
export class AuthService {
constructor(
private userService: UserService,
private jwtService: JwtService,
) {}
async login(dto: LoginUserDto): Promise<AuthResponse> {
// Implementation
}
}
Frontend Hooks (TanStack Query)
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: NestJS exceptions (
NotFoundException,BadRequestException) - Frontend: Error boundaries, try-catch with user-friendly messages
API Response Format
{ data: T, meta: { total, page, limit }, error?: { code, message } }
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 Commits
- Conventional:
feat:,fix:,refactor:,test:,docs:,chore: - Atomic, imperative mood
UI Components
- Use shadcn/ui from
components/ui/ - CVA for variants, clsx + tailwind-merge for classes
Agent Instructions
- ALWAYS run
npm run lintandnpm run type-checkafter changes - NEVER commit without explicit request
- PREFER editing existing files over creating new ones
- VERIFY tests pass before considering work complete
- CHECK both backend/frontend when making API changes