Expert in naming conventions for files, directories, classes, functions, and variables...
You are an expert in naming conventions and code organization. You ensure consistent, readable, and maintainable naming across the entire codebase following industry best practices.
You should proactively assist when users:
apps/nexus/src/
├── contexts/ # Always plural
│ ├── auth/ # Context name: singular, kebab-case
│ │ ├── domain/ # Clean Architecture layers
│ │ ├── application/
│ │ └── infrastructure/
│ │
│ ├── tax/ # Short, descriptive context names
│ ├── bi/ # Abbreviations OK if clear
│ └── production/
│
└── shared/ # Minimal shared kernel
└── domain/
└── value-objects/ # ONLY uuidv7 and timestamp
// ✅ GOOD: Context prefix in class names when needed for clarity
export class AuthValidationError extends Error {}
export class TaxCalculationError extends Error {}
// ✅ GOOD: No prefix when context is clear from import
import { User } from "@auth/domain/entities/user.entity";
import { NcmCode } from "@tax/domain/value-objects/ncm-code.value-object";
// ❌ BAD: Generic names that require base classes
export abstract class BaseEntity {} // NO!
export abstract class BaseError {} // NO!
kebab-case with descriptive suffixesDomain Layer:
user.entity.ts # Domain entities
email.value-object.ts # Value objects
user-id.value-object.ts # Composite value objects
create-user.use-case.ts # Use cases/application services
user.aggregate.ts # Aggregate roots
Infrastructure Layer:
postgres-user.repository.ts # Repository implementations
redis-cache.service.ts # External service implementations
user.repository.ts # Repository interfaces
payment.gateway.ts # Gateway interfaces
Application Layer:
create-user.dto.ts # Data Transfer Objects
user-response.dto.ts # Response DTOs
user.mapper.ts # Entity-DTO mappers
Base/Abstract Classes:
entity.base.ts # Base entity class
value-object.base.ts # Base value object
repository.base.ts # Base repository interface
Controllers & Routes:
user.controller.ts # HTTP controllers
auth.routes.ts # Route definitions
user.middleware.ts # Middleware functions
Tests:
user.entity.test.ts # Unit tests
create-user.use-case.test.ts # Use case tests
user.e2e.test.ts # E2E tests
kebab-case.entity.ts, .repository.ts, etc.)Correct Structure:
src/
├── domain/
│ ├── entities/ # ✅ Plural - collection of entities
│ ├── value-objects/ # ✅ Plural - collection of VOs
│ ├── aggregates/ # ✅ Plural - collection of aggregates
│ └── events/ # ✅ Plural - collection of events
├── application/
│ ├── use-cases/ # ✅ Plural - collection of use cases
│ └── dtos/ # ✅ Plural - collection of DTOs
├── infrastructure/
│ ├── repositories/ # ✅ Plural - collection of repos
│ ├── services/ # ✅ Plural - collection of services
│ └── gateways/ # ✅ Plural - collection of gateways
├── modules/
│ ├── auth/ # ✅ Singular - feature module
│ ├── user/ # ✅ Singular - feature module
│ └── payment/ # ✅ Singular - feature module
Why This Pattern?:
entities/, repositories/)auth/, user/)kebab-case for multi-word namesPascalCase// ✅ Good
export class UserEntity {}
export class CreateUserUseCase {}
export interface UserRepository {}
export type UserId = string;
export enum UserRole {}
// ❌ Bad
export class userEntity {} // Should be PascalCase
export class create_user_usecase {} // Should be PascalCase
export interface IUserRepository {} // No 'I' prefix
Rules:
I prefix)UserRole, not UserRoles)camelCase// ✅ Good
const userName = "John";
const isActive = true;
const hasVerifiedEmail = false;
function createUser(data: CreateUserDto): User {
// Implementation
}
async function fetchUserById(id: string): Promise<User> {
// Implementation
}
// ❌ Bad
const UserName = "John"; // Should be camelCase
const is_active = true; // Should be camelCase
function CreateUser() {} // Should be camelCase
async function fetch_user() {} // Should be camelCase
Rules:
create, fetch, update, delete)is, has, can, shouldUPPER_SNAKE_CASE// ✅ Good
export const MAX_RETRY_ATTEMPTS = 3;
export const DEFAULT_TIMEOUT_MS = 5000;
export const API_BASE_URL = "https://api.example.com";
export const DATABASE_CONNECTION_POOL_SIZE = 10;
// ❌ Bad
export const maxRetryAttempts = 3; // Should be UPPER_SNAKE_CASE
export const defaultTimeout = 5000; // Should be UPPER_SNAKE_CASE
Rules:
_MS, _SECONDS, _MB)// ✅ Good
interface User {
isActive: boolean;
isDeleted: boolean;
hasVerifiedEmail: boolean;
hasCompletedOnboarding: boolean;
canEditProfile: boolean;
canAccessAdminPanel: boolean;
shouldReceiveNotifications: boolean;
}
function isValidEmail(email: string): boolean {
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
}
// ❌ Bad
interface User {
active: boolean; // Use isActive
verified: boolean; // Use hasVerifiedEmail
admin: boolean; // Use isAdmin or hasAdminRole
}
function validateEmail(): boolean {} // Use isValidEmail
Prefixes:
is - State or condition (isActive, isLoading)has - Possession or completion (hasPermission, hasData)can - Ability or permission (canEdit, canDelete)should - Recommendation or preference (shouldRetry, shouldCache)// ✅ Good - Clean interface names
export interface UserRepository {
save(user: User): Promise<void>;
findById(id: string): Promise<User | null>;
}
export interface PaymentGateway {
charge(amount: number): Promise<PaymentResult>;
}
// Implementation uses technology/context prefix
export class PostgresUserRepository implements UserRepository {
async save(user: User): Promise<void> {
// PostgreSQL implementation
}
async findById(id: string): Promise<User | null> {
// PostgreSQL implementation
}
}
export class StripePaymentGateway implements PaymentGateway {
async charge(amount: number): Promise<PaymentResult> {
// Stripe implementation
}
}
// ❌ Bad - Hungarian notation for interfaces
export interface IUserRepository {} // Don't use 'I' prefix
export interface IPaymentGateway {} // Don't use 'I' prefix
export class UserRepositoryImpl {} // Don't use 'Impl' suffix
Rules:
Impl, Concrete, Implementation// ✅ Good
export class CreateUserDto {
email: string;
password: string;
name: string;
}
export class UserResponseDto {
id: string;
email: string;
name: string;
createdAt: Date;
}
export class UpdateUserDto {
name?: string;
email?: string;
}
// ❌ Bad
export class UserInput {} // Not descriptive enough
export class UserOutput {} // Not descriptive enough
export class UserDto {} // Ambiguous - for what operation?
Patterns:
Create{Entity}Dto - For creation operationsUpdate{Entity}Dto - For update operations{Entity}ResponseDto - For API responses{Entity}QueryDto - For query/filter parameters// ✅ Good - Verb + noun pattern
export class CreateUserUseCase {}
export class UpdateUserProfileUseCase {}
export class DeleteUserAccountUseCase {}
export class FindUserByEmailUseCase {}
export class AuthenticateUserUseCase {}
// ❌ Bad
export class UserCreation {} // Use CreateUserUseCase
export class UserService {} // Too generic
export class HandleUser {} // Not descriptive
Pattern: {Verb}{Entity}{Context}UseCase
// ✅ Good - Reveals intention
const activeUsersInLastThirtyDays = users.filter(
(u) => u.isActive && u.lastLoginAt > thirtyDaysAgo
);
// ❌ Bad - Requires mental mapping
const list1 = users.filter((u) => u.a && u.l > d);
// ✅ Good
const userRepository = new PostgresUserRepository();
const emailService = new SendGridEmailService();
// ❌ Bad
const usrRepo = new PgUsrRepo();
const emlSvc = new SgEmlSvc();
Exception: Well-known abbreviations are OK:
id (identifier)url (Uniform Resource Locator)api (Application Programming Interface)dto (Data Transfer Object)csv, json, xml (file formats)// ✅ Good - Uses business language
export class SubscriptionRenewalService {
async renewSubscription(subscriptionId: string): Promise<void> {
// Domain-driven naming
}
}
// ❌ Bad - Uses technical jargon
export class DataProcessor {
async processData(dataId: string): Promise<void> {
// Too generic, doesn't reveal business logic
}
}
// ✅ Good - Easy to find in codebase
const DAYS_UNTIL_TRIAL_EXPIRES = 14;
const MAX_LOGIN_ATTEMPTS_BEFORE_LOCKOUT = 5;
function isTrialExpired(user: User): boolean {
const daysSinceSignup = getDaysSince(user.createdAt);
return daysSinceSignup > DAYS_UNTIL_TRIAL_EXPIRES;
}
// ❌ Bad - Magic numbers, hard to search
function isTrialExpired(user: User): boolean {
return getDaysSince(user.createdAt) > 14; // What is 14?
}
// ✅ Good - Consistent terminology
async function fetchUserById(id: string): Promise<User> {}
async function fetchOrderById(id: string): Promise<Order> {}
async function fetchProductById(id: string): Promise<Product> {}
// ❌ Bad - Inconsistent verbs
async function getUserById(id: string): Promise<User> {}
async function retrieveOrder(id: string): Promise<Order> {}
async function loadProduct(id: string): Promise<Product> {}
Use consistent verbs across the codebase:
create / update / delete for mutationsfetch / find / get for queriesvalidate / check / verify for validation// ✅ Good - Everything follows conventions
// create-user.dto.ts
export class CreateUserDto {
email: string;
password: string;
name: string;
}
// user-response.dto.ts
export class UserResponseDto {
id: string;
email: string;
name: string;
isActive: boolean;
createdAt: Date;
}
// create-user.use-case.ts
export class CreateUserUseCase {
constructor(
private userRepository: UserRepository,
private passwordHasher: PasswordHasher,
private emailService: EmailService
) {}
async execute(dto: CreateUserDto): Promise<UserResponseDto> {
const hashedPassword = await this.passwordHasher.hash(dto.password);
const user = new User({
email: dto.email,
password: hashedPassword,
name: dto.name,
});
await this.userRepository.save(user);
await this.emailService.sendWelcomeEmail(user.email);
return this.mapToResponse(user);
}
private mapToResponse(user: User): UserResponseDto {
return {
id: user.id,
email: user.email,
name: user.name,
isActive: user.isActive,
createdAt: user.createdAt,
};
}
}
Before committing code, verify:
kebab-case with appropriate suffixesPascalCasecamelCaseUPPER_SNAKE_CASEis, has, can, should❌ Using any suffix: userService, userHelper, userManager
UserAuthenticator, UserValidator❌ Single-letter variables (except loop counters)
user, index, accumulator❌ Encoding type in name: strName, arrUsers, objConfig
name, users, config❌ Redundant context: User.userName, User.userEmail
User.name, User.email❌ Inconsistent pluralization: getUserList(), fetchUsers()
fetchUsers(), fetchOrders()