Naming Patterns
Naming conventions for branches, files, database objects, packages, and identifiers -- and why they are the way they are.
Consistent naming makes code searchable, reviewable, and predictable. This page collects all naming conventions in one place. For the automated enforcement of identifier naming, see Complexity and Naming.
Identifier Naming
Identifier casing is enforced by @typescript-eslint/naming-convention. The full rule configuration and rationale is documented in Complexity and Naming. The summary:
| What | Convention | Example |
|---|---|---|
| Variables | camelCase (default), PascalCase (React components), UPPER_CASE (constants) | userId, UserCard, MAX_RETRIES |
| Functions | camelCase, PascalCase (React components) | createWidget, WidgetList |
| Route handlers | UPPER_CASE only | GET, POST, DELETE |
| Parameters | camelCase, PascalCase | tenantId, Component |
| Types, interfaces, classes | PascalCase | CreateWidgetInput, UserProfile |
| Type parameters | PascalCase with T prefix | TResult, TItem |
| Object literal properties | Exempt (match external APIs) | -- |
| Type properties | camelCase, snake_case (external API boundaries) | createdAt, model_id |
| Destructured variables | Exempt (match source shape) | -- |
Package Naming
All internal packages use the @repo/ scope. Packages are not published to npm -- the scope is for internal organization only.
| Pattern | Convention | Example |
|---|---|---|
| Internal packages | @repo/<name> | @repo/db, @repo/auth, @repo/ai |
| Config packages | @repo/config-<tool> | @repo/config-eslint, @repo/config-typescript |
| App packages | @repo/<app-name> | @repo/web |
File and Directory Naming
| What | Convention | Example |
|---|---|---|
| Source files | kebab-case.ts | tenant-context.ts, plan-engine.ts |
| React components | kebab-case.tsx | widget-card.tsx, sidebar-nav.tsx |
| Test files | <source>.test.ts | tenant-context.test.ts |
| Index files | index.ts | Re-exports only; no business logic |
| Schema files | kebab-case.ts in schema/ | organizations.ts, ai-usage.ts |
| Migration files | Drizzle-generated names | 0001_initial.sql |
| Feature directories | kebab-case | research-engine/, plan-management/ |
Branch Naming
Branch names come from Linear. Use Linear's suggested format, which ties every branch to a ticket:
kyleolson512/tro-14-phase-0-gate-review
kyleolson512/tro-22-ai-api-layer-claude-api-integration
The pattern is: <github-username>/<ticket-id>-<slug>.
Git Worktree Naming
When using git worktrees for parallel agent development:
git worktree add .trees/<feature-name> -b feature/<feature-name>
The .trees/ directory is gitignored. Worktree branches use the feature/<name> prefix.
Database Object Naming
| What | Convention | Example |
|---|---|---|
| Tables | snake_case, plural | organizations, ai_usage, research_plans |
| Columns | snake_case | created_at, organization_id, model_id |
| Foreign keys | <referenced_table_singular>_id | user_id, organization_id |
| Indexes | Drizzle-generated (based on columns) | -- |
| Enums | snake_case | plan_status, org_type |
| Enum values | snake_case | in_progress, completed, failed |
Environment Variable Naming
| What | Convention | Example |
|---|---|---|
| Server-side env vars | UPPER_SNAKE_CASE | DATABASE_URL, BETTER_AUTH_SECRET |
| Client-side env vars | NEXT_PUBLIC_ prefix | NEXT_PUBLIC_APP_URL |
| Location | apps/web/.env (not root .env) | -- |
The root .env is only used by database scripts. Application env vars go in apps/web/.env.
Linear Ticket Naming
| What | Convention | Example |
|---|---|---|
| Ticket IDs | TRO-<number> | TRO-22, TRO-97 |
| Labels | kebab-case | foundation, week-2, doc-update-request |
| Milestones | Descriptive name | "Document Update Requests" |
Related Pages
- Delivery -- Architecture Enforcement -- Complexity and Naming -- the ESLint rules that enforce identifier naming
- Data & Storage -- Schema Design -- Table Conventions -- database naming in detail
- Delivery -- Dependency Management -- package naming within the catalog system