Code Style Guide
Coding conventions and best practices.
General Principles
- Readability first - Code is read more than written
- Consistency - Follow established patterns
- Simplicity - Prefer simple over clever
- Self-documenting - Clear names over comments
TypeScript
Naming Conventions
// Variables and functions: camelCase
const userName = 'John';
function getUserName() {}
// Classes and types: PascalCase
class UserService {}
type UserProfile = {};
interface UserData {}
// Constants: SCREAMING_SNAKE_CASE
const MAX_RETRIES = 3;
// Files: kebab-case
// user-service.ts
// get-user-data.ts
Functions
// Prefer arrow functions for callbacks
const numbers = [1, 2, 3].map((n) => n * 2);
// Use regular functions for methods
function calculateTotal(items: Item[]): number {
return items.reduce((sum, item) => sum + item.price, 0);
}
// Destructure parameters
function createUser({ name, email }: CreateUserInput) {
// ...
}
Types
// Prefer interfaces for objects
interface User {
id: string;
name: string;
email: string;
}
// Use types for unions and utilities
type Status = 'pending' | 'active' | 'inactive';
type UserWithPosts = User & { posts: Post[] };
// Always type function parameters and returns
function getUser(id: string): Promise<User | null> {
// ...
}
React
Component Structure
// 1. Imports
import { useState } from 'react';
import { Button } from '@/components/ui/button';
// 2. Types
interface UserCardProps {
user: User;
onEdit: (id: string) => void;
}
// 3. Component
export function UserCard({ user, onEdit }: UserCardProps) {
// 3a. Hooks
const [isLoading, setIsLoading] = useState(false);
// 3b. Handlers
const handleEdit = () => {
onEdit(user.id);
};
// 3c. Render
return (
<div className="p-4 border rounded">
<h3>{user.name}</h3>
<Button onClick={handleEdit}>Edit</Button>
</div>
);
}
Naming
// Components: PascalCase
function UserProfile() {}
// Hooks: use prefix
function useUserData() {}
// Event handlers: handle prefix
const handleClick = () => {};
const handleSubmit = () => {};
File Organization
src/
├── app/ # Routes/pages
├── components/
│ ├── ui/ # Base UI components
│ └── features/ # Feature-specific components
├── lib/
│ ├── utils.ts # Utility functions
│ └── constants.ts # Shared constants
├── services/ # API/external services
├── hooks/ # Custom hooks
└── types/ # Shared types
Comments
// Good: Explain WHY, not WHAT
// Retry with exponential backoff to handle rate limiting
const delay = Math.pow(2, attempt) * 1000;
// Bad: Describes what code already says
// Increment counter by 1
counter++;
// Use TODO for future work
// TODO: Implement caching for better performance
Error Handling
// Always handle errors explicitly
try {
const result = await fetchUser(id);
return result;
} catch (error) {
console.error('Failed to fetch user:', error);
throw new UserFetchError('Unable to fetch user', { cause: error });
}
// Use custom error classes
class UserFetchError extends Error {
constructor(message: string, options?: ErrorOptions) {
super(message, options);
this.name = 'UserFetchError';
}
}
Imports
// Order: external, internal, relative
import { useState } from 'react'; // 1. External
import { cn } from '@/lib/utils'; // 2. Internal (alias)
import { Button } from '../components/Button'; // 3. Relative
Formatting
- Use Prettier for automatic formatting
- 2 space indentation
- Single quotes for strings
- Trailing commas
- No semicolons (or always - pick one)
// .prettierrc
{
"semi": true,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "es5"
}