Skip to main content

Best Practices Guide

Development Workflow

Git Hooks (Automated)

Pre-commit hooks automatically run:

  • ESLint with auto-fix
  • Prettier formatting

This ensures all committed code is clean and consistent.

Code Quality

Linting:

pnpm lint          # Check for issues
pnpm lint:fix # Auto-fix issues

Formatting:

pnpm format        # Format all files
pnpm format:check # Verify formatting

Project Structure

Import Paths

Use path aliases for clean imports:

// ✅ GOOD
import { logger } from '@/lib/logger';
import { UserService } from '@/domains/user/user.service';

// ❌ BAD
import { logger } from '../../../lib/logger';

Component Organization (Frontend)

See .cursor/rules/React-Component-Architecture.mdc for detailed guidance:

  • Default to reusable components in /components
  • Extend existing components instead of creating duplicates
  • Inline components only for page-specific logic

Service Organization (Backend)

Domain-driven structure:

src/domains/
├── user/
│ ├── user.controller.ts
│ ├── user.service.ts
│ ├── user.module.ts
│ └── dto/
├── guild/
└── event/

Logging

Frontend (Web)

import { log } from '@/lib/logger';

log.debug('Debug info');
log.info('User action completed');
log.warn('Rate limit approaching');
log.error('Operation failed', error);

Backend (API)

import { Logger } from '@/lib/logger';

export class UserService {
private readonly logger = new Logger('UserService');

async findUser(id: string) {
this.logger.info(`Finding user ${id}`);
// ...
}
}

Error Handling

Backend

Use the global exception filter for consistent error responses:

// Errors are automatically caught and formatted
throw new NotFoundException('User not found');
throw new BadRequestException('Invalid input');

All errors return this format:

{
"statusCode": 404,
"message": "User not found",
"timestamp": "2024-01-31T...",
"path": "/api/users/123",
"method": "GET"
}

Environment Variables

Validation

Environment variables are validated on startup. Missing or invalid vars will prevent the app from starting.

See apps/api/src/config/env.validation.ts for required variables.

Configuration Files

  • .env - Local development (git-ignored)
  • .env.example - Template with all required variables

Database

Migrations

# Create migration
pnpm db:migrate

# Apply migrations
pnpm db:push

# Generate Prisma client
pnpm db:generate

Best practices:

  • Always create migrations for schema changes
  • Never modify migration files after they're committed
  • Test migrations locally before pushing

API Design

Versioning

All endpoints should use versioning:

@Controller('api/v1/users')

Response Format

Success:

{
"data": { ... },
"meta": { ... }
}

Error:

{
"statusCode": 400,
"message": "Validation failed",
"errors": { ... }
}

Security

Authentication

  • OAuth only (Battle.net, Discord)
  • JWT tokens for session management
  • Never store passwords

Authorization

Use CASL for permission checks:

@CheckAbilities({ action: Action.Update, subject: 'Guild' })

See apps/api/src/auth/abilities/ for implementation.

Performance

Frontend

  • Use TanStack Query for server state
  • Lazy load routes
  • Optimize images
  • Avoid inline functions in render

Backend

  • Use database indexes appropriately
  • Cache external API responses
  • Use background jobs for heavy operations
  • Implement rate limiting

Testing

Running Tests

# Frontend
pnpm --filter web test

# Backend
pnpm --filter api test

Writing Tests

Unit tests:

  • Test business logic in services
  • Mock external dependencies
  • Use descriptive test names

Integration tests:

  • Test API endpoints
  • Use test database
  • Clean up after tests

Code Style

TypeScript

  • Use explicit types where it improves clarity
  • any is allowed but use sparingly
  • Prefer interfaces over types for objects
  • Use enums for fixed sets of values

Naming Conventions

  • Components: PascalCase
  • Files: kebab-case.ts
  • Functions/variables: camelCase
  • Constants: UPPER_SNAKE_CASE
  • Types/Interfaces: PascalCase

Comments

  • Explain why, not what
  • Use JSDoc for public APIs
  • Keep comments up to date
  • Remove commented-out code

Git Workflow

Commit Messages

Use conventional commits:

feat: add user profile page
fix: resolve authentication bug
docs: update API documentation
refactor: simplify user service

Branches

  • main - production-ready code
  • Feature branches from main
  • Descriptive branch names: feat/user-profiles

Documentation

  • Update README when adding features
  • Keep API documentation in sync
  • Document complex business logic
  • Update this file when practices change

Test