Universal coding standards, best practices, and patterns for TypeScript, JavaScript, React, and Node.js development.
Add this skill
npx mdskills install sickn33/cc-skill-coding-standardsComprehensive coding standards with excellent examples, patterns, and anti-patterns for modern TypeScript development
1---2name: coding-standards3description: Universal coding standards, best practices, and patterns for TypeScript, JavaScript, React, and Node.js development.4author: affaan-m5version: "1.0"6---78# Coding Standards & Best Practices910Universal coding standards applicable across all projects.1112## Code Quality Principles1314### 1. Readability First15- Code is read more than written16- Clear variable and function names17- Self-documenting code preferred over comments18- Consistent formatting1920### 2. KISS (Keep It Simple, Stupid)21- Simplest solution that works22- Avoid over-engineering23- No premature optimization24- Easy to understand > clever code2526### 3. DRY (Don't Repeat Yourself)27- Extract common logic into functions28- Create reusable components29- Share utilities across modules30- Avoid copy-paste programming3132### 4. YAGNI (You Aren't Gonna Need It)33- Don't build features before they're needed34- Avoid speculative generality35- Add complexity only when required36- Start simple, refactor when needed3738## TypeScript/JavaScript Standards3940### Variable Naming4142```typescript43// ✅ GOOD: Descriptive names44const marketSearchQuery = 'election'45const isUserAuthenticated = true46const totalRevenue = 10004748// ❌ BAD: Unclear names49const q = 'election'50const flag = true51const x = 100052```5354### Function Naming5556```typescript57// ✅ GOOD: Verb-noun pattern58async function fetchMarketData(marketId: string) { }59function calculateSimilarity(a: number[], b: number[]) { }60function isValidEmail(email: string): boolean { }6162// ❌ BAD: Unclear or noun-only63async function market(id: string) { }64function similarity(a, b) { }65function email(e) { }66```6768### Immutability Pattern (CRITICAL)6970```typescript71// ✅ ALWAYS use spread operator72const updatedUser = {73 ...user,74 name: 'New Name'75}7677const updatedArray = [...items, newItem]7879// ❌ NEVER mutate directly80user.name = 'New Name' // BAD81items.push(newItem) // BAD82```8384### Error Handling8586```typescript87// ✅ GOOD: Comprehensive error handling88async function fetchData(url: string) {89 try {90 const response = await fetch(url)9192 if (!response.ok) {93 throw new Error(`HTTP ${response.status}: ${response.statusText}`)94 }9596 return await response.json()97 } catch (error) {98 console.error('Fetch failed:', error)99 throw new Error('Failed to fetch data')100 }101}102103// ❌ BAD: No error handling104async function fetchData(url) {105 const response = await fetch(url)106 return response.json()107}108```109110### Async/Await Best Practices111112```typescript113// ✅ GOOD: Parallel execution when possible114const [users, markets, stats] = await Promise.all([115 fetchUsers(),116 fetchMarkets(),117 fetchStats()118])119120// ❌ BAD: Sequential when unnecessary121const users = await fetchUsers()122const markets = await fetchMarkets()123const stats = await fetchStats()124```125126### Type Safety127128```typescript129// ✅ GOOD: Proper types130interface Market {131 id: string132 name: string133 status: 'active' | 'resolved' | 'closed'134 created_at: Date135}136137function getMarket(id: string): Promise<Market> {138 // Implementation139}140141// ❌ BAD: Using 'any'142function getMarket(id: any): Promise<any> {143 // Implementation144}145```146147## React Best Practices148149### Component Structure150151```typescript152// ✅ GOOD: Functional component with types153interface ButtonProps {154 children: React.ReactNode155 onClick: () => void156 disabled?: boolean157 variant?: 'primary' | 'secondary'158}159160export function Button({161 children,162 onClick,163 disabled = false,164 variant = 'primary'165}: ButtonProps) {166 return (167 <button168 onClick={onClick}169 disabled={disabled}170 className={`btn btn-${variant}`}171 >172 {children}173 </button>174 )175}176177// ❌ BAD: No types, unclear structure178export function Button(props) {179 return <button onClick={props.onClick}>{props.children}</button>180}181```182183### Custom Hooks184185```typescript186// ✅ GOOD: Reusable custom hook187export function useDebounce<T>(value: T, delay: number): T {188 const [debouncedValue, setDebouncedValue] = useState<T>(value)189190 useEffect(() => {191 const handler = setTimeout(() => {192 setDebouncedValue(value)193 }, delay)194195 return () => clearTimeout(handler)196 }, [value, delay])197198 return debouncedValue199}200201// Usage202const debouncedQuery = useDebounce(searchQuery, 500)203```204205### State Management206207```typescript208// ✅ GOOD: Proper state updates209const [count, setCount] = useState(0)210211// Functional update for state based on previous state212setCount(prev => prev + 1)213214// ❌ BAD: Direct state reference215setCount(count + 1) // Can be stale in async scenarios216```217218### Conditional Rendering219220```typescript221// ✅ GOOD: Clear conditional rendering222{isLoading && <Spinner />}223{error && <ErrorMessage error={error} />}224{data && <DataDisplay data={data} />}225226// ❌ BAD: Ternary hell227{isLoading ? <Spinner /> : error ? <ErrorMessage error={error} /> : data ? <DataDisplay data={data} /> : null}228```229230## API Design Standards231232### REST API Conventions233234```235GET /api/markets # List all markets236GET /api/markets/:id # Get specific market237POST /api/markets # Create new market238PUT /api/markets/:id # Update market (full)239PATCH /api/markets/:id # Update market (partial)240DELETE /api/markets/:id # Delete market241242# Query parameters for filtering243GET /api/markets?status=active&limit=10&offset=0244```245246### Response Format247248```typescript249// ✅ GOOD: Consistent response structure250interface ApiResponse<T> {251 success: boolean252 data?: T253 error?: string254 meta?: {255 total: number256 page: number257 limit: number258 }259}260261// Success response262return NextResponse.json({263 success: true,264 data: markets,265 meta: { total: 100, page: 1, limit: 10 }266})267268// Error response269return NextResponse.json({270 success: false,271 error: 'Invalid request'272}, { status: 400 })273```274275### Input Validation276277```typescript278import { z } from 'zod'279280// ✅ GOOD: Schema validation281const CreateMarketSchema = z.object({282 name: z.string().min(1).max(200),283 description: z.string().min(1).max(2000),284 endDate: z.string().datetime(),285 categories: z.array(z.string()).min(1)286})287288export async function POST(request: Request) {289 const body = await request.json()290291 try {292 const validated = CreateMarketSchema.parse(body)293 // Proceed with validated data294 } catch (error) {295 if (error instanceof z.ZodError) {296 return NextResponse.json({297 success: false,298 error: 'Validation failed',299 details: error.errors300 }, { status: 400 })301 }302 }303}304```305306## File Organization307308### Project Structure309310```311src/312├── app/ # Next.js App Router313│ ├── api/ # API routes314│ ├── markets/ # Market pages315│ └── (auth)/ # Auth pages (route groups)316├── components/ # React components317│ ├── ui/ # Generic UI components318│ ├── forms/ # Form components319│ └── layouts/ # Layout components320├── hooks/ # Custom React hooks321├── lib/ # Utilities and configs322│ ├── api/ # API clients323│ ├── utils/ # Helper functions324│ └── constants/ # Constants325├── types/ # TypeScript types326└── styles/ # Global styles327```328329### File Naming330331```332components/Button.tsx # PascalCase for components333hooks/useAuth.ts # camelCase with 'use' prefix334lib/formatDate.ts # camelCase for utilities335types/market.types.ts # camelCase with .types suffix336```337338## Comments & Documentation339340### When to Comment341342```typescript343// ✅ GOOD: Explain WHY, not WHAT344// Use exponential backoff to avoid overwhelming the API during outages345const delay = Math.min(1000 * Math.pow(2, retryCount), 30000)346347// Deliberately using mutation here for performance with large arrays348items.push(newItem)349350// ❌ BAD: Stating the obvious351// Increment counter by 1352count++353354// Set name to user's name355name = user.name356```357358### JSDoc for Public APIs359360```typescript361/**362 * Searches markets using semantic similarity.363 *364 * @param query - Natural language search query365 * @param limit - Maximum number of results (default: 10)366 * @returns Array of markets sorted by similarity score367 * @throws {Error} If OpenAI API fails or Redis unavailable368 *369 * @example370 * ```typescript371 * const results = await searchMarkets('election', 5)372 * console.log(results[0].name) // "Trump vs Biden"373 * ```374 */375export async function searchMarkets(376 query: string,377 limit: number = 10378): Promise<Market[]> {379 // Implementation380}381```382383## Performance Best Practices384385### Memoization386387```typescript388import { useMemo, useCallback } from 'react'389390// ✅ GOOD: Memoize expensive computations391const sortedMarkets = useMemo(() => {392 return markets.sort((a, b) => b.volume - a.volume)393}, [markets])394395// ✅ GOOD: Memoize callbacks396const handleSearch = useCallback((query: string) => {397 setSearchQuery(query)398}, [])399```400401### Lazy Loading402403```typescript404import { lazy, Suspense } from 'react'405406// ✅ GOOD: Lazy load heavy components407const HeavyChart = lazy(() => import('./HeavyChart'))408409export function Dashboard() {410 return (411 <Suspense fallback={<Spinner />}>412 <HeavyChart />413 </Suspense>414 )415}416```417418### Database Queries419420```typescript421// ✅ GOOD: Select only needed columns422const { data } = await supabase423 .from('markets')424 .select('id, name, status')425 .limit(10)426427// ❌ BAD: Select everything428const { data } = await supabase429 .from('markets')430 .select('*')431```432433## Testing Standards434435### Test Structure (AAA Pattern)436437```typescript438test('calculates similarity correctly', () => {439 // Arrange440 const vector1 = [1, 0, 0]441 const vector2 = [0, 1, 0]442443 // Act444 const similarity = calculateCosineSimilarity(vector1, vector2)445446 // Assert447 expect(similarity).toBe(0)448})449```450451### Test Naming452453```typescript454// ✅ GOOD: Descriptive test names455test('returns empty array when no markets match query', () => { })456test('throws error when OpenAI API key is missing', () => { })457test('falls back to substring search when Redis unavailable', () => { })458459// ❌ BAD: Vague test names460test('works', () => { })461test('test search', () => { })462```463464## Code Smell Detection465466Watch for these anti-patterns:467468### 1. Long Functions469```typescript470// ❌ BAD: Function > 50 lines471function processMarketData() {472 // 100 lines of code473}474475// ✅ GOOD: Split into smaller functions476function processMarketData() {477 const validated = validateData()478 const transformed = transformData(validated)479 return saveData(transformed)480}481```482483### 2. Deep Nesting484```typescript485// ❌ BAD: 5+ levels of nesting486if (user) {487 if (user.isAdmin) {488 if (market) {489 if (market.isActive) {490 if (hasPermission) {491 // Do something492 }493 }494 }495 }496}497498// ✅ GOOD: Early returns499if (!user) return500if (!user.isAdmin) return501if (!market) return502if (!market.isActive) return503if (!hasPermission) return504505// Do something506```507508### 3. Magic Numbers509```typescript510// ❌ BAD: Unexplained numbers511if (retryCount > 3) { }512setTimeout(callback, 500)513514// ✅ GOOD: Named constants515const MAX_RETRIES = 3516const DEBOUNCE_DELAY_MS = 500517518if (retryCount > MAX_RETRIES) { }519setTimeout(callback, DEBOUNCE_DELAY_MS)520```521522**Remember**: Code quality is not negotiable. Clear, maintainable code enables rapid development and confident refactoring.
Full transparency — inspect the skill content before installing.