ContributorPatterns
Naming Conventions
Naming Conventions
Consistent naming patterns across the Toast codebase.
Files and Directories
| Type | Convention | Example |
|---|---|---|
| Directories | kebab-case | my-feature/ |
| TypeScript files | kebab-case | content.service.ts |
| Test files | kebab-case | content.test.ts |
| React components | PascalCase | LoginForm.tsx |
| Config files | kebab-case | vitest.config.ts |
File Suffixes
| Suffix | Purpose | Example |
|---|---|---|
.service.ts | Business logic layer | content.service.ts |
.repository.ts | Data access layer | content.repository.ts |
.controller.ts | HTTP handlers | content.controller.ts |
.test.ts | Test file | content.test.ts |
.integration.test.ts | Integration test | content.integration.test.ts |
TypeScript
| Element | Convention | Example |
|---|---|---|
| Variables | camelCase | contentItems |
| Functions | camelCase | findById() |
| Classes | PascalCase | ContentService |
| Interfaces | PascalCase | ContentResponse |
| Type aliases | PascalCase | CreateContentInput |
| Enums | PascalCase | ContentStatus |
| Enum values | PascalCase | ContentStatus.Published |
| Constants | SCREAMING_SNAKE_CASE | MAX_RETRIES |
Type Naming Patterns
// Response types (returned from services)
interface ContentResponse { ... }
// Input types (received by services)
interface CreateContentInput { ... }
// Database row types (from Drizzle inference)
type ContentRow = typeof content.$inferSelect;
type CreateContentData = typeof content.$inferInsert;
// Zod schema types
type CreateContent = z.infer<typeof CreateContentSchema>;Database
| Element | Convention | Example |
|---|---|---|
| Table names | snake_case | user_sessions |
| Column names | snake_case | created_at |
| Index names | idx_{table}_{column} | idx_content_site_id |
| Enum type names | snake_case | content_status |
| Enum values | snake_case | 'draft', 'published' |
Drizzle Schema
Column definitions use snake_case strings, TypeScript uses camelCase:
export const content = pgTable('content', {
id: uuid('id').defaultRandom().primaryKey(),
siteId: uuid('site_id').notNull(), // DB: site_id, TS: siteId
createdAt: timestamp('created_at', ...), // DB: created_at, TS: createdAt
});API
Endpoints
| Pattern | Example |
|---|---|
| List resources | GET /api/content |
| Get single resource | GET /api/content/:id |
| Create resource | POST /api/content |
| Update resource | PUT /api/content/:id |
| Delete resource | DELETE /api/content/:id |
| Custom action | POST /api/content/:id/publish |
Response Fields
JSON responses use camelCase:
{
"id": "uuid",
"siteId": "uuid",
"createdAt": "2024-01-01T00:00:00.000Z",
"updatedAt": "2024-01-01T00:00:00.000Z"
}Environment Variables
| Convention | Example |
|---|---|
| SCREAMING_SNAKE_CASE | DATABASE_URL |
| Prefixed by scope | VITE_API_URL (client) |
Git
Branch Names
feature/123-add-user-auth
fix/456-content-validation
docs/update-readme
refactor/extract-serviceCommit Messages
Use Conventional Commit format:
<type>(optional-scope): short summary
feat(api): add content publishing endpoint
fix(api): validate empty titles
docs: update API documentation
refactor(api): move persistence logic into repositoryPull Request Titles
Use the same Conventional Commit format as commits:
feat(admin): improve media library filtering
fix(ci): handle cache miss in Docker build
docs: clarify Railway setup prerequisitesSee AGENTS.md for full commit message guidelines.