| name | coding-standards |
| description | Project coding standards and conventions. Loaded automatically when writing or reviewing code to ensure consistency. |
| user-invocable | false |
Project Coding Standards
These standards apply automatically when working with code in this project.
General Principles
- Clarity over cleverness: Code should be obvious, not clever
- Consistency over perfection: Follow existing patterns even if you'd do it differently
- Simple over complex: Choose the simplest solution that works
- Tested over documented: Tests are better than comments for explaining behavior
Code Style
Naming Conventions
class UserRepository {}
function getUserById(id: string) {}
const MAX_RETRY_ATTEMPTS = 3;
class Example {
private _internalState: string;
}
const isValid = true;
const hasPermission = false;
const shouldRetry = true;
File Organization
src/
├── components/ # UI components
│ ├── Button/
│ │ ├── Button.tsx
│ │ ├── Button.test.tsx
│ │ └── index.ts # Re-exports
├── hooks/ # React hooks
├── utils/ # Pure utility functions
├── services/ # API and external services
├── types/ # TypeScript type definitions
└── constants/ # App-wide constants
Import Order
Always order imports:
- External libraries
- Internal modules (absolute imports)
- Relative imports
- Types (if separate)
import React from 'react';
import { format } from 'date-fns';
import { Button } from '@/components/Button';
import { useAuth } from '@/hooks/useAuth';
import { helper } from './utils';
import styles from './Component.module.css';
import type { User } from '@/types';
Error Handling
Always handle errors explicitly
try {
const result = await riskyOperation();
return result;
} catch (error) {
logger.error('Operation failed:', error);
throw new ApplicationError('Failed to complete operation', { cause: error });
}
try {
await riskyOperation();
} catch (error) {
}
Use custom error types
class ValidationError extends Error {
constructor(message: string, public field: string) {
super(message);
this.name = 'ValidationError';
}
}
Testing
Test Structure: Arrange-Act-Assert
test('should calculate total with tax', () => {
const items = [{ price: 100 }, { price: 200 }];
const taxRate = 0.1;
const total = calculateTotal(items, taxRate);
assert.strictEqual(total, 330);
});
Test Naming
Use descriptive names that explain the scenario:
test('returns 404 when user does not exist')
test('throws ValidationError when email is invalid')
test('caches result after first successful fetch')
test('test user')
test('error case')
test('it works')
What to Test
- Happy path: Normal successful flow
- Edge cases: Empty arrays, null values, boundary conditions
- Error cases: Invalid input, network failures, permission denied
- Side effects: Database writes, API calls, events emitted
TypeScript
Prefer explicit types over inference for public APIs
export function processUser(id: string): Promise<User> {
}
function formatDate(date: Date) {
return date.toISOString();
}
Use unknown over any
function parseJSON(input: string): unknown {
return JSON.parse(input);
}
function parseJSON(input: string): any {
return JSON.parse(input);
}
Avoid assertion unless absolutely necessary
function isUser(obj: unknown): obj is User {
return typeof obj === 'object' && obj !== null && 'id' in obj;
}
const user = data as User;
Comments
When to Comment
- Why, not what: Explain decisions, not syntax
- Gotchas: Warn about non-obvious behavior
- TODOs: Technical debt that needs addressing
const debouncedSearch = debounce(search, 300);
const x = 5;
Avoid Comments When Code Can Be Clear
function isEligibleForDiscount(user: User): boolean {
return user.isPremium && user.purchaseCount > 10;
}
function check(u: User): boolean {
return u.p && u.c > 10;
}
Git Conventions
Commit Messages
Follow Conventional Commits:
type(scope): subject
body
footer
Types:
feat: New feature
fix: Bug fix
docs: Documentation only
refactor: Code change that neither fixes nor adds feature
test: Adding or updating tests
chore: Maintenance (dependencies, config)
Examples:
feat(auth): add password reset functionality
Implements email-based password reset flow with token expiration.
Closes #123
fix(api): handle null response from external service
The third-party API occasionally returns null instead of empty array.
Added null check to prevent runtime errors.
Branch Naming
feature/short-description
fix/issue-number-description
refactor/component-name
docs/what-is-documented
Performance
Avoid Premature Optimization
- Profile before optimizing
- Optimize the bottleneck, not everything
- Prefer readability unless performance is measured and critical
Common Patterns
const memoized = useMemo(() => expensiveOperation(data), [data]);
const debouncedHandler = debounce(handleInput, 300);
const HeavyComponent = lazy(() => import('./HeavyComponent'));
Security
Never trust user input
function createUser(input: unknown) {
const validated = userSchema.parse(input);
const sanitized = sanitize(validated);
return db.users.create(sanitized);
}
Use environment variables for secrets
const apiKey = process.env.API_KEY;
const apiKey = 'sk-abc123...';
Additional Resources
For more detailed specifications:
Notes
This is a background knowledge skill that loads automatically when Claude writes or reviews code.
It ensures consistency across the codebase without requiring manual invocation.