This guide covers best practices, coding standards, development workflows, and tools for contributing to the Hackathon Template project.
This project follows clean code principles and modern TypeScript best practices:
- Type Safety First: No
anytypes allowed - Clean Architecture: Clear separation of concerns
- Testable Code: Write code that's easy to test
- Documentation: Code should be self-documenting with clear naming
- Consistency: Follow established patterns throughout the codebase
- Use English for all code and documentation
- Always declare types for variables and functions (parameters and return values)
- Avoid using
any- create proper types instead - Use JSDoc to document public classes and methods
- Don't leave blank lines within functions
- One export per file
- PascalCase for classes:
UserService,CreateUserCommand - camelCase for variables, functions, and methods:
getUserById,isLoading - kebab-case for file and directory names:
user-service.ts,create-user/ - UPPERCASE for environment variables:
DATABASE_URL,JWT_SECRET - Complete words instead of abbreviations (except standard ones like API, URL)
Acceptable abbreviations:
i,jfor loopserrfor errorsctxfor contextsreq,res,nextfor middleware parameters
- Write short functions with a single purpose (< 20 instructions)
- Name functions with a verb:
createUser,validateEmail - Boolean functions should use
isX,hasX,canX:isValid,hasPermission - Use early returns to avoid nesting
- Use arrow functions for simple functions (< 3 instructions)
- Use named functions for complex logic
- Use default parameters instead of checking for null/undefined
- Encapsulate data in composite types instead of using primitives
- Prefer immutability
- Use
readonlyfor data that doesn't change - Use
as constfor literals that don't change
- One module per main domain/route
- One controller per route with secondary controllers for sub-routes
- Organize in folders:
models/,dtos/,services/,entities/ - Use CQRS pattern for complex business logic
- Implement repository pattern for data access
@ApiTags("Feature")
@Controller({ version: "1", path: "feature" })
export class FeatureController {
constructor(private readonly featureService: FeatureService) {}
@Public()
@Post()
@ApiOperation({ summary: "Create feature" })
@ApiCreatedResponse({ type: CreateFeatureResponseDto })
async create(@Body() dto: CreateFeatureRequestDto) {
return await this.featureService.create(dto);
}
}@Injectable()
export class FeatureService {
constructor(
private readonly commandBus: CommandBus,
private readonly queryBus: QueryBus,
) {}
async create(
dto: CreateFeatureRequestDto,
): Promise<CreateFeatureResponseDto> {
return this.commandBus.execute(new CreateFeatureCommand(dto));
}
}- Use functional components with hooks
- Keep components focused and small
- Extract custom hooks for reusable logic
- Use TypeScript interfaces for props
- Co-locate related files (components, styles, tests)
- Use feature-based folder structure
- Prefix private folders with underscore:
_api/,_utils/
- Use React Query for server state
- Use local state for UI state
- Lift state up when needed by multiple components
- Use
@hackathon/uipackage for all UI components - Add new shadcn/ui components via:
cd packages/ui && npx shadcn@latest add <component> - Always fix imports manually after adding shadcn/ui components:
- Change
import { cn } from "src/lib/utils"toimport { cn } from "../../lib/utils"
- Change
- Export new components from
packages/ui/src/index.ts - Follow the "new-york" style variant and zinc color scheme
-
Environment Setup
# Install dependencies pnpm install # Set up environment cp .env.example .env # Edit .env with your values # Start database pnpm db:up # Start development servers pnpm dev
-
Verify Setup
- API:
http://localhost:4000/health - Web:
http://localhost:3000 - Swagger:
http://localhost:4000/api - Emails:
http://localhost:3002
- API:
# Pull latest changes
git pull origin main
# Install any new dependencies
pnpm install
# Start development servers
pnpm dev-
Create feature branch
git checkout -b feature/user-authentication
-
Run quality checks
pnpm lint # Check code style pnpm check-types # Type checking pnpm test # Run tests
-
Commit changes
git add . git commit -m "feat: add user authentication"
The project uses strict ESLint rules:
- No unused variables
- Consistent import ordering
- TypeScript-specific rules
- React hooks rules
- Accessibility rules
Automatic code formatting with:
- 2-space indentation
- Single quotes
- Trailing commas
- Import sorting
- Modify schema in
packages/db/src/schemas/ - Generate migration
pnpm --filter=db db:generate
- Review migration in
packages/db/drizzle/ - Apply migration
pnpm --filter=db db:migrate
# Reset database with fresh data
pnpm db:reset
# Open database studio
pnpm --filter=db db:studio
# Seed additional data
pnpm --filter=db db:seed- Always backup before migrations
- Test migrations on staging first
- Use transactions for complex migrations
- Document breaking changes
- Use NestJS built-in logger
- Add debug logs in development
- Use Swagger UI for API testing
- Check database queries in Drizzle Studio
- Use React DevTools
- Use React Query DevTools (enabled in development)
- Check network requests in browser DevTools
- Use console.log sparingly (remove before commit)
# Check if database is running
docker ps
# Restart database
pnpm db:down && pnpm db:up# Check what's using a port
lsof -i :4000
# Kill process
kill -9 <PID>- Ensure all packages are built:
pnpm build - Restart TypeScript server in VS Code
- Check for circular dependencies
- Use database indexes appropriately
- Implement pagination for large datasets
- Use connection pooling
- Cache expensive operations
- Profile API endpoints
- Use React Query for caching
- Implement code splitting
- Optimize images and assets
- Use proper loading states
- Minimize bundle size
- Index frequently queried columns
- Use appropriate data types
- Avoid N+1 queries
- Use database-level constraints
- Use JSDoc for public APIs
- Include examples in documentation
- Document complex business logic
- Keep README files updated
- Use Swagger decorators
- Provide example requests/responses
- Document error responses
- Include authentication requirements
- Validate all inputs with class-validator
- Sanitize user data
- Use parameterized queries
- Implement rate limiting
- Use strong password requirements
- Implement proper session management
- Use HTTPS in production
- Validate JWT tokens properly
- Never commit secrets to git
- Use environment variables for config
- Rotate secrets regularly
- Use different secrets per environment
- All tests passing
- No linting errors
- Environment variables configured
- Database migrations ready
- Error handling implemented
- Logging configured
- Performance tested
# Production environment variables
NODE_ENV=production
DATABASE_URL=postgresql://...
JWT_SECRET=strong-secret-key
EMAIL_API_KEY=...# Feature branch naming
feature/user-authentication
fix/login-validation
chore/update-dependencies
# Commit message format
feat: add user authentication
fix: resolve login validation issue
docs: update API documentation- Use clear, descriptive commit messages
- Document breaking changes
- Communicate architectural decisions
- Share knowledge through code comments
This development guide ensures consistent, high-quality code across the project while maintaining developer productivity and code maintainability.