Skip to content

Naming Conventions

Quick Reference

  • When to use: Naming any variable, function, file, or type in the codebase
  • Enforcement: Required - inconsistent naming causes confusion
  • Impact if violated: Medium - readability and maintainability issues

The Rule

Use consistent naming conventions based on the element type:

  • camelCase for variables, functions, and most file names
  • PascalCase for types, interfaces, classes, constructors, and Lambda directories
  • SCREAMING_SNAKE_CASE for true constants and environment variable names
  • kebab-case for package names only (@mantleframework/create-mantle-app)

Naming Styles

camelCase

Pattern: First letter lowercase, subsequent words capitalized

Used for:

  • Variables: userName, isActive, hasPermission
  • Functions: fetchUserData, calculateTotal, validateInput
  • File names: userService.ts, apiHelpers.ts, queryMetrics.ts
  • Object properties: user.firstName, config.maxRetries
  • Function parameters: function greet(firstName, lastName)

PascalCase

Pattern: First letter uppercase, subsequent words capitalized

Used for:

  • TypeScript interfaces: interface UserProfile
  • Type aliases: type UserId = string
  • Classes: class UserQueries, class AppError
  • Enums: enum DatabaseOperation
  • Lambda directories: src/lambdas/api/GetUser/, src/lambdas/standalone/ProcessFile/
  • Decorator names: @RequiresTable, @Traceable

SCREAMING_SNAKE_CASE

Pattern: All uppercase letters with underscores

Used for:

  • True application constants: MAX_RETRIES, DEFAULT_TIMEOUT
  • Environment variable names: AWS_REGION, ENVIRONMENT, METRICS_NAMESPACE
  • Module-level configuration: const BATCH_SIZE = 10

Examples

Correct

typescript
// Variables and functions (camelCase)
const userName = 'John'
const isLoggedIn = true
function calculateTotalPrice(basePrice: number, taxRate: number) {
  return basePrice * (1 + taxRate)
}

// Types and interfaces (PascalCase)
interface UserProfile {
  firstName: string
  lastName: string
  emailAddress: string
}

type UserId = string

class UserQueries {
  static async getById(userId: UserId): Promise<UserProfile> {
    // Implementation
  }
}

// Constants (SCREAMING_SNAKE_CASE)
const MAX_RETRY_ATTEMPTS = 3
const DEFAULT_TIMEOUT_MS = 5000

// Environment variables via @mantleframework/env
import {getRequiredEnv} from '@mantleframework/env'

const region = getRequiredEnv('AWS_REGION')
const environment = getRequiredEnv('ENVIRONMENT')

Incorrect

typescript
// Wrong: PascalCase for variables
const UserName = 'John'  // Should be userName

// Wrong: snake_case for functions
function calculate_total_price() {}  // Should be calculateTotalPrice

// Wrong: camelCase for interfaces
interface userProfile {}  // Should be UserProfile

// Wrong: Direct process.env access
const region = process.env.AWS_REGION!  // Should use getRequiredEnv()

// Wrong: kebab-case for TypeScript files
// user-service.ts  // Should be userService.ts

Special Cases

Environment Variables

Environment variable names use SCREAMING_CASE. Always access via @mantleframework/env:

typescript
// Correct - Use getRequiredEnv() / getOptionalEnv()
import {getRequiredEnv, getOptionalEnv} from '@mantleframework/env'

const region = getRequiredEnv('AWS_REGION')
const logLevel = getOptionalEnv('LOG_LEVEL', 'info')

// Wrong - Direct process.env access
const region = process.env.AWS_REGION!

Lambda Function Directories

Lambda function directories use PascalCase, organized by category:

# Correct - PascalCase with category subdirectories
src/lambdas/api/GetUser/
src/lambdas/api/ListFiles/
src/lambdas/standalone/ProcessFile/
src/lambdas/standalone/DatabaseMigration/

# Incorrect
src/lambdas/get-user/        # kebab-case
src/lambdas/list_files/      # snake_case
src/lambdas/listFiles/       # camelCase

Why PascalCase: Matches the Lambda function name in AWS, making it easy to correlate code with infrastructure.

Package Names

Package names use kebab-case (npm convention):

@mantleframework/core
@mantleframework/env
@mantleframework/create-mantle-app
@mantleframework/observability

Acronyms and Initialisms

Treat acronyms as words:

typescript
// Correct
const apiUrl = 'https://api.example.com'
const userId = '123'
class HttpClient {}

// Incorrect
const APIURL = 'https://api.example.com'
const userID = '123'
class HTTPClient {}

Boolean Variables

Use descriptive prefixes:

typescript
// Good boolean names
const isActive = true
const hasPermission = false
const canEdit = true
const shouldRetry = false

// Poor boolean names
const active = true      // Unclear if boolean
const permission = false  // Sounds like an object

Rationale

Consistent naming conventions:

  1. Improve readability - Developers immediately understand element types
  2. Reduce cognitive load - No need to guess or remember special cases
  3. Enable tooling - IDEs can better understand and refactor code
  4. Facilitate collaboration - Team members use same patterns
  5. Prevent bugs - Clear distinction between types and values

Enforcement

Automated Checks

  • ESLint @typescript-eslint/naming-convention - Validates interface, type, and class casing
  • ESLint local-rules/env-validation - Catches direct process.env usage
  • dprint - Formats code consistently (does not enforce naming)

Manual Review

During code review, check for:

  • Consistent application of conventions
  • Clear, descriptive names
  • Appropriate use of each naming style
  • No mixing of styles within same category

This convention ensures code readability and consistency across all Mantle packages. Follow it strictly for new code.