Back to skills
SkillHub ClubShip Full StackFull StackFrontend

wednesday-dev

Technical development guidelines for Wednesday Solutions projects. Enforces import ordering, complexity limits, naming conventions, TypeScript best practices, and code quality standards for React/Next.js applications.

Packaged view

This page reorganizes the original catalog entry around fit, installability, and workflow context first. The original raw source lives below.

Stars
140
Hot score
95
Updated
March 19, 2026
Overall rating
C2.9
Composite score
2.9
Best-practice grade
C61.1

Install command

npx @skill-hub/cli install wednesday-solutions-ai-agent-skills-wednesday-dev

Repository

wednesday-solutions/ai-agent-skills

Skill path: skills/wednesday-dev

Technical development guidelines for Wednesday Solutions projects. Enforces import ordering, complexity limits, naming conventions, TypeScript best practices, and code quality standards for React/Next.js applications.

Open repository

Best for

Primary workflow: Ship Full Stack.

Technical facets: Full Stack, Frontend.

Target audience: everyone.

License: MIT.

Original source

Catalog source: SkillHub Club.

Repository owner: wednesday-solutions.

This is still a mirrored public skill entry. Review the repository before installing into production workflows.

What it helps with

  • Install wednesday-dev into Claude Code, Codex CLI, Gemini CLI, or OpenCode workflows
  • Review https://github.com/wednesday-solutions/ai-agent-skills before adding wednesday-dev to shared team environments
  • Use wednesday-dev for development workflows

Works across

Claude CodeCodex CLIGemini CLIOpenCode

Favorites: 0.

Sub-skills: 0.

Aggregator: No.

Original source / Raw SKILL.md

---
name: wednesday-dev
description: Technical development guidelines for Wednesday Solutions projects. Enforces import ordering, complexity limits, naming conventions, TypeScript best practices, and code quality standards for React/Next.js applications.
license: MIT
metadata:
  author: wednesday-solutions
  version: "1.0"
compatibility: Next.js 14+, React 18+, TypeScript 5+
---

# Wednesday Technical Development Guidelines

This skill enforces code quality standards for Wednesday Solutions projects. Follow these guidelines to maintain consistency, readability, and maintainability across the codebase.

## 1. Import Order

Imports must follow a strict ordering pattern. The project uses `@trivago/prettier-plugin-sort-imports` to enforce this automatically.

### Required Order

```typescript
// 1. React (always first)
import React, { useState, useEffect } from 'react'

// 2. Next.js imports
import { useRouter } from 'next/navigation'
import Image from 'next/image'

// 3. State management (Recoil, Redux)
import { useSelector } from 'react-redux'

// 4. UI libraries (MUI, Radix)
import { Button } from '@mui/material'

// 5. Path alias imports (@/)
import { useAuth } from '@/lib/hooks/useAuth'
import { API_ROUTES } from '@/lib/constants'

// 6. External packages
import { z } from 'zod'
import { motion } from 'framer-motion'

// 7. Internal components
import { Header } from 'components/Header'

// 8. Relative imports (sibling/parent)
import { utils } from './utils'
import { types } from '../types'
```

### Rules

- Each import group must be separated by a blank line
- Imports within each group should be alphabetically sorted
- Use type imports for TypeScript types: `import type { User } from '@/types'`
- Avoid wildcard imports (`import * as`) unless necessary

## 2. Code Complexity

### Cyclomatic Complexity

**Maximum allowed: 8** (stricter than industry standard of 10)

Functions exceeding this limit must be refactored. See [references/COMPLEXITY.md](references/COMPLEXITY.md) for detailed strategies.

### Quick Remediation

| Complexity | Action Required |
|------------|-----------------|
| 1-4        | Good - easy to test |
| 5-7        | Acceptable - consider simplifying |
| 8          | At limit - refactor if adding logic |
| 9+         | Must refactor before merging |

### How to Reduce Complexity

1. **Extract helper functions** - Break large functions into smaller, focused ones
2. **Use early returns** - Replace nested conditions with guard clauses
3. **Replace conditionals with polymorphism** - Use strategy pattern for complex branching
4. **Simplify boolean expressions** - Extract complex conditions into named variables
5. **Use lookup tables** - Replace switch statements with object maps

```typescript
// BAD: High complexity
function getDiscount(user: User, items: Item[]) {
  let discount = 0
  if (user.isPremium) {
    if (items.length > 10) {
      discount = 20
    } else if (items.length > 5) {
      discount = 10
    } else {
      discount = 5
    }
  } else {
    if (items.length > 10) {
      discount = 10
    } else if (items.length > 5) {
      discount = 5
    }
  }
  return discount
}

// GOOD: Low complexity with lookup table
const DISCOUNT_TABLE = {
  premium: { large: 20, medium: 10, small: 5 },
  regular: { large: 10, medium: 5, small: 0 },
} as const

function getCartSize(count: number): 'large' | 'medium' | 'small' {
  if (count > 10) return 'large'
  if (count > 5) return 'medium'
  return 'small'
}

function getDiscount(user: User, items: Item[]) {
  const tier = user.isPremium ? 'premium' : 'regular'
  const size = getCartSize(items.length)
  return DISCOUNT_TABLE[tier][size]
}
```

### File Size Limits

- **Max file lines**: 250
- **Max function lines**: 350
- **Max line length**: 120 characters

## 3. Naming Conventions

### Components & Classes

Use **PascalCase** for React components, classes, types, and interfaces.

```typescript
// Components
function UserProfile() { }
function PaymentCard() { }

// Types & Interfaces
interface UserProfileProps { }
type PaymentMethod = 'card' | 'bank'

// Classes
class AuthService { }
```

### Functions & Variables

Use **camelCase** for functions, variables, hooks, and object properties.

```typescript
// Functions
function fetchUserData() { }
function calculateTotal() { }

// Variables
const isLoading = true
const userProfile = { }

// Hooks
function useAuth() { }
function useLocalStorage() { }
```

### Constants & Enums

Use **UPPER_SNAKE_CASE** for constants and enum values.

```typescript
// Constants
const API_BASE_URL = 'https://api.example.com'
const MAX_RETRY_ATTEMPTS = 3

// Enums
enum UserRole {
  ADMIN = 'ADMIN',
  USER = 'USER',
  GUEST = 'GUEST',
}
```

### Boolean Variables

Prefix with `is`, `has`, `should`, `can`, or `will` for clarity.

```typescript
// Good
const isAuthenticated = true
const hasPermission = false
const shouldRefetch = true
const canEdit = user.role === 'ADMIN'

// Bad
const authenticated = true
const permission = false
const refetch = true
```

### Files & Folders

| Type | Convention | Example |
|------|------------|---------|
| Component files | PascalCase | `UserProfile.tsx` |
| Hook files | camelCase with `use` prefix | `useAuth.ts` |
| Utility files | camelCase | `formatDate.ts` |
| Constant files | camelCase | `apiRoutes.ts` |
| Type files | camelCase | `user.types.ts` |
| Test files | Match source + `.test` | `UserProfile.test.tsx` |
| Folders | camelCase | `components/`, `hooks/` |

### Descriptive Naming

Names should be self-documenting:

```typescript
// Bad - unclear intent
const d = new Date()
const arr = users.filter(u => u.a)
function proc(x: number) { }

// Good - clear intent
const currentDate = new Date()
const activeUsers = users.filter(user => user.isActive)
function processPayment(amount: number) { }
```

## 4. TypeScript Best Practices

### Strict Type Safety

- Enable strict mode in `tsconfig.json`
- Avoid `any` type - use `unknown` and narrow types
- Use explicit return types for public functions
- Leverage discriminated unions for state

```typescript
// Use discriminated unions
type AsyncState<T> =
  | { status: 'idle' }
  | { status: 'loading' }
  | { status: 'success'; data: T }
  | { status: 'error'; error: Error }

// Narrow types properly
function processValue(value: unknown) {
  if (typeof value === 'string') {
    return value.toUpperCase()
  }
  if (typeof value === 'number') {
    return value.toFixed(2)
  }
  throw new Error('Unsupported type')
}
```

### Type Imports

Separate type imports from value imports:

```typescript
import { useState } from 'react'
import type { FC, ReactNode } from 'react'

import { fetchUser } from '@/lib/api'
import type { User, UserRole } from '@/types'
```

## 5. React Patterns

### Component Structure

Follow this order within components:

1. Type definitions (props interface)
2. Component function declaration
3. Hooks (useState, useEffect, custom hooks)
4. Derived state / computations
5. Event handlers
6. Effects
7. Return statement (JSX)

```typescript
interface UserCardProps {
  userId: string
  onSelect?: (user: User) => void
}

export function UserCard({ userId, onSelect }: UserCardProps) {
  // 1. Hooks
  const [isExpanded, setIsExpanded] = useState(false)
  const { data: user, isLoading } = useUser(userId)

  // 2. Derived state
  const displayName = user ? `${user.firstName} ${user.lastName}` : 'Unknown'

  // 3. Event handlers
  const handleClick = () => {
    setIsExpanded(!isExpanded)
    onSelect?.(user)
  }

  // 4. Early returns for loading/error states
  if (isLoading) return <Skeleton />
  if (!user) return null

  // 5. Main render
  return (
    <Card onClick={handleClick}>
      <CardTitle>{displayName}</CardTitle>
      {isExpanded && <CardContent>{user.bio}</CardContent>}
    </Card>
  )
}
```

### Use Client Directive

Mark client components explicitly:

```typescript
'use client'

import { useState } from 'react'
// ... client-side component
```

## 6. Forbidden Patterns

### No Console Statements

Console statements are forbidden in production code. Use proper logging utilities.

```typescript
// Forbidden
console.log('debug:', data)
console.error('Error:', err)

// Use structured logging or remove before commit
```

### No Magic Numbers/Strings

Extract to named constants:

```typescript
// Bad
if (retryCount > 3) { }
if (status === 'active') { }

// Good
const MAX_RETRIES = 3
const STATUS_ACTIVE = 'active'

if (retryCount > MAX_RETRIES) { }
if (status === STATUS_ACTIVE) { }
```

### No Unused Code

- Remove unused imports (enforced by `eslint-plugin-unused-imports`)
- Delete commented-out code
- Remove unused variables (prefix with `_` only if intentionally unused)

## 7. Testing Requirements

### Unit Tests

- Use Jest with React Testing Library
- Test file naming: `ComponentName.test.tsx`
- Focus on user behavior, not implementation details

```typescript
import { render, screen, fireEvent } from '@testing-library/react'
import { UserCard } from './UserCard'

describe('UserCard', () => {
  it('displays user name correctly', () => {
    render(<UserCard userId="123" />)
    expect(screen.getByText('John Doe')).toBeInTheDocument()
  })

  it('calls onSelect when clicked', () => {
    const onSelect = jest.fn()
    render(<UserCard userId="123" onSelect={onSelect} />)
    fireEvent.click(screen.getByRole('button'))
    expect(onSelect).toHaveBeenCalledWith(expect.objectContaining({ id: '123' }))
  })
})
```

### E2E Tests

- Use Playwright for end-to-end tests
- Test file naming: `feature.spec.ts`
- Test critical user flows

## 8. Security Considerations

- Sanitize HTML with DOMPurify before rendering
- Validate all user inputs with Zod schemas
- Never expose sensitive data in client-side code
- Use environment variables for secrets
- Implement CSRF protection for forms

## 9. Performance Guidelines

- Use `next/dynamic` for code splitting
- Implement proper loading states
- Memoize expensive computations with `useMemo`
- Avoid unnecessary re-renders with `React.memo`
- Use image optimization with `next/image`

---

For detailed examples and edge cases, see [references/COMPLEXITY.md](references/COMPLEXITY.md).


---

## Referenced Files

> The following files are referenced in this skill and included for context.

### references/COMPLEXITY.md

```markdown
# Complexity Reference Guide

This document provides detailed strategies for managing code complexity in Wednesday Solutions projects.

## Understanding Cyclomatic Complexity

Cyclomatic complexity measures the number of linearly independent paths through a function. Each decision point (if, else, case, &&, ||, ternary, catch) adds 1 to the complexity.

### Counting Complexity

```typescript
function example(a: boolean, b: boolean, c: number) {  // Base: 1
  if (a) {                    // +1
    doSomething()
  } else if (b) {             // +1
    doSomethingElse()
  }

  switch (c) {
    case 1:                   // +1
      handleOne()
      break
    case 2:                   // +1
      handleTwo()
      break
    default:
      handleDefault()
  }

  const result = a && b       // +1 (short-circuit)
    ? 'both'
    : 'not both'              // +1 (ternary)

  try {
    riskyOperation()
  } catch (e) {               // +1
    handleError(e)
  }

  return result
}
// Total complexity: 8
```

## Refactoring Strategies

### 1. Extract Early Returns (Guard Clauses)

Transform nested conditions into flat guard clauses.

```typescript
// Before: Complexity 5
function processOrder(order: Order) {
  if (order) {
    if (order.items.length > 0) {
      if (order.isPaid) {
        if (order.shippingAddress) {
          return shipOrder(order)
        } else {
          return { error: 'No shipping address' }
        }
      } else {
        return { error: 'Order not paid' }
      }
    } else {
      return { error: 'No items' }
    }
  } else {
    return { error: 'Invalid order' }
  }
}

// After: Complexity 4
function processOrder(order: Order) {
  if (!order) return { error: 'Invalid order' }
  if (order.items.length === 0) return { error: 'No items' }
  if (!order.isPaid) return { error: 'Order not paid' }
  if (!order.shippingAddress) return { error: 'No shipping address' }

  return shipOrder(order)
}
```

### 2. Replace Conditionals with Lookup Tables

Transform switch/if-else chains into object lookups.

```typescript
// Before: Complexity 6
function getStatusColor(status: string): string {
  if (status === 'pending') {
    return 'yellow'
  } else if (status === 'approved') {
    return 'green'
  } else if (status === 'rejected') {
    return 'red'
  } else if (status === 'cancelled') {
    return 'gray'
  } else if (status === 'processing') {
    return 'blue'
  } else {
    return 'black'
  }
}

// After: Complexity 1
const STATUS_COLORS: Record<string, string> = {
  pending: 'yellow',
  approved: 'green',
  rejected: 'red',
  cancelled: 'gray',
  processing: 'blue',
}

function getStatusColor(status: string): string {
  return STATUS_COLORS[status] ?? 'black'
}
```

### 3. Extract Complex Conditions

Move boolean expressions into named variables or functions.

```typescript
// Before: Hard to read, complexity embedded in condition
function canUserEditPost(user: User, post: Post) {
  if ((user.role === 'admin' || user.role === 'moderator') &&
      post.status !== 'archived' &&
      (post.authorId === user.id || user.permissions.includes('edit_any'))) {
    return true
  }
  return false
}

// After: Self-documenting, same complexity but readable
function canUserEditPost(user: User, post: Post) {
  const isPrivilegedUser = user.role === 'admin' || user.role === 'moderator'
  const isPostEditable = post.status !== 'archived'
  const hasEditPermission = post.authorId === user.id || user.permissions.includes('edit_any')

  return isPrivilegedUser && isPostEditable && hasEditPermission
}
```

### 4. Use Strategy Pattern

Replace complex branching with polymorphism.

```typescript
// Before: Complexity 5
function calculatePrice(item: Item, userType: string) {
  let price = item.basePrice

  if (userType === 'premium') {
    price = price * 0.8
    if (item.quantity > 10) {
      price = price * 0.95
    }
  } else if (userType === 'wholesale') {
    price = price * 0.7
    if (item.quantity > 100) {
      price = price * 0.9
    }
  } else {
    if (item.quantity > 5) {
      price = price * 0.98
    }
  }

  return price
}

// After: Complexity 1 per function
interface PricingStrategy {
  calculate(basePrice: number, quantity: number): number
}

const pricingStrategies: Record<string, PricingStrategy> = {
  premium: {
    calculate: (basePrice, quantity) => {
      const discounted = basePrice * 0.8
      return quantity > 10 ? discounted * 0.95 : discounted
    },
  },
  wholesale: {
    calculate: (basePrice, quantity) => {
      const discounted = basePrice * 0.7
      return quantity > 100 ? discounted * 0.9 : discounted
    },
  },
  regular: {
    calculate: (basePrice, quantity) => {
      return quantity > 5 ? basePrice * 0.98 : basePrice
    },
  },
}

function calculatePrice(item: Item, userType: string) {
  const strategy = pricingStrategies[userType] ?? pricingStrategies.regular
  return strategy.calculate(item.basePrice, item.quantity)
}
```

### 5. Decompose Functions

Split large functions into smaller, focused ones.

```typescript
// Before: Complexity 10
function processUserRegistration(data: RegistrationData) {
  // Validate email
  if (!data.email || !data.email.includes('@')) {
    return { error: 'Invalid email' }
  }

  // Validate password
  if (!data.password || data.password.length < 8) {
    return { error: 'Password too short' }
  }
  if (!/[A-Z]/.test(data.password)) {
    return { error: 'Password needs uppercase' }
  }
  if (!/[0-9]/.test(data.password)) {
    return { error: 'Password needs number' }
  }

  // Check existing user
  const existing = findUserByEmail(data.email)
  if (existing) {
    return { error: 'Email already registered' }
  }

  // Create user
  const user = createUser(data)
  if (!user) {
    return { error: 'Failed to create user' }
  }

  // Send welcome email
  const emailSent = sendWelcomeEmail(user)
  if (!emailSent) {
    // Log but don't fail
    logError('Welcome email failed')
  }

  return { success: true, user }
}

// After: Each function has complexity 2-3
function validateEmail(email: string): string | null {
  if (!email || !email.includes('@')) return 'Invalid email'
  return null
}

function validatePassword(password: string): string | null {
  if (!password || password.length < 8) return 'Password too short'
  if (!/[A-Z]/.test(password)) return 'Password needs uppercase'
  if (!/[0-9]/.test(password)) return 'Password needs number'
  return null
}

function processUserRegistration(data: RegistrationData) {
  const emailError = validateEmail(data.email)
  if (emailError) return { error: emailError }

  const passwordError = validatePassword(data.password)
  if (passwordError) return { error: passwordError }

  const existing = findUserByEmail(data.email)
  if (existing) return { error: 'Email already registered' }

  const user = createUser(data)
  if (!user) return { error: 'Failed to create user' }

  sendWelcomeEmail(user).catch(logError)

  return { success: true, user }
}
```

### 6. Use Optional Chaining and Nullish Coalescing

Reduce null checks with modern JavaScript operators.

```typescript
// Before: Complexity increases with each check
function getUserCity(user: User | null) {
  if (user) {
    if (user.address) {
      if (user.address.city) {
        return user.address.city
      }
    }
  }
  return 'Unknown'
}

// After: Complexity 1
function getUserCity(user: User | null) {
  return user?.address?.city ?? 'Unknown'
}
```

## Cognitive Complexity

Beyond cyclomatic complexity, consider **cognitive complexity** - how hard code is for humans to understand.

### Factors That Increase Cognitive Load

1. **Nesting depth** - Each level of nesting multiplies difficulty
2. **Breaking linear flow** - break, continue, early returns in loops
3. **Multiple conditions** - Complex boolean expressions
4. **Recursion** - Harder to trace mentally

### Good Practices

```typescript
// Avoid deep nesting
// Bad
function processItems(items: Item[]) {
  for (const item of items) {
    if (item.isValid) {
      if (item.type === 'special') {
        for (const subItem of item.children) {
          if (subItem.active) {
            // 4 levels deep - hard to follow
          }
        }
      }
    }
  }
}

// Good - flatten with early continues
function processItems(items: Item[]) {
  for (const item of items) {
    if (!item.isValid) continue
    if (item.type !== 'special') continue

    processSpecialItem(item)
  }
}

function processSpecialItem(item: Item) {
  for (const subItem of item.children) {
    if (!subItem.active) continue

    // Process at max 1 level deep
  }
}
```

## ESLint Configuration

The project enforces complexity via ESLint:

```javascript
// eslint.config.mjs
{
  rules: {
    'complexity': ['error', 8],
    'max-lines': ['error', 250],
    'max-lines-per-function': ['error', 350],
    'max-depth': ['error', 4],
    'max-nested-callbacks': ['error', 3],
  }
}
```

## Tools for Measuring Complexity

1. **ESLint** - Reports violations during development
2. **SonarQube** - Comprehensive code quality analysis
3. **VS Code Extensions** - CodeMetrics, SonarLint

## When to Accept Higher Complexity

Sometimes complexity is unavoidable:

1. **State machines** - Complex by nature, but use libraries like XState
2. **Parsers** - Consider using parser generators
3. **Algorithm implementations** - Document thoroughly, test extensively
4. **Legacy integration** - Isolate complexity, add comprehensive tests

In these cases:
- Add `// eslint-disable-next-line complexity` with justification
- Ensure 100% test coverage for the complex function
- Document the complexity in comments
- Consider if a library could handle it better

```



---

## Skill Companion Files

> Additional files collected from the skill directory layout.

### references/NAMING.md

```markdown
# Naming Conventions Reference

Detailed naming conventions for Wednesday Solutions React/TypeScript projects.

## Quick Reference Table

| Element | Convention | Example |
|---------|------------|---------|
| Components | PascalCase | `UserProfile`, `PaymentCard` |
| Hooks | camelCase with `use` prefix | `useAuth`, `useLocalStorage` |
| Functions | camelCase, verb-first | `fetchUser`, `calculateTotal` |
| Variables | camelCase | `isLoading`, `userData` |
| Constants | UPPER_SNAKE_CASE | `API_BASE_URL`, `MAX_RETRIES` |
| Types/Interfaces | PascalCase | `User`, `PaymentMethod` |
| Enums | PascalCase name, UPPER_SNAKE_CASE values | `UserRole.ADMIN` |
| Files (components) | PascalCase | `UserProfile.tsx` |
| Files (utilities) | camelCase | `formatDate.ts` |
| Folders | camelCase | `components/`, `hooks/` |
| CSS classes | kebab-case (Tailwind) | `text-primary`, `bg-gray-100` |

## Detailed Guidelines

### React Components

```typescript
// Component naming - PascalCase
function UserProfileCard() { }
function PaymentMethodSelector() { }
function NavigationHeader() { }

// Higher-order components - prefix with 'with'
function withAuthentication(Component: FC) { }
function withErrorBoundary(Component: FC) { }

// Render prop components - descriptive name
function DataFetcher({ render }: DataFetcherProps) { }
function MouseTracker({ children }: MouseTrackerProps) { }
```

### Custom Hooks

```typescript
// Always prefix with 'use'
function useAuth() { }
function useLocalStorage<T>(key: string) { }
function usePagination(options: PaginationOptions) { }
function useDebounce<T>(value: T, delay: number) { }

// Query hooks - use 'use' + resource name
function useUser(id: string) { }
function useProducts(filters: ProductFilters) { }
function useOrderHistory(userId: string) { }

// Mutation hooks - use 'use' + action + resource
function useCreateUser() { }
function useUpdateProduct() { }
function useDeleteOrder() { }
```

### Functions

```typescript
// Action functions - start with verb
function fetchUserData() { }
function calculateTotalPrice() { }
function validateEmailFormat() { }
function formatCurrency() { }
function parseApiResponse() { }

// Boolean returning functions - prefix with 'is', 'has', 'can', 'should'
function isValidEmail(email: string): boolean { }
function hasPermission(user: User, action: string): boolean { }
function canEditPost(user: User, post: Post): boolean { }
function shouldRefetch(lastFetched: Date): boolean { }

// Event handlers - prefix with 'handle' or 'on'
function handleSubmit() { }
function handleInputChange() { }
function onUserSelect() { }
function onModalClose() { }

// Transformer functions - 'to' + target format
function toKebabCase(str: string) { }
function toApiFormat(data: FormData) { }
function toDisplayDate(date: Date) { }

// Factory functions - 'create' + object type
function createUser(data: UserData): User { }
function createApiClient(config: Config): ApiClient { }
```

### Variables

```typescript
// Boolean variables - 'is', 'has', 'should', 'can', 'will'
const isAuthenticated = true
const hasErrors = errors.length > 0
const shouldShowModal = isOpen && !isLoading
const canSubmit = isValid && !isSubmitting
const willRedirect = status === 'success'

// Arrays - plural nouns
const users: User[] = []
const selectedItems: Item[] = []
const errorMessages: string[] = []

// Objects - singular nouns
const user: User = { }
const config: Config = { }
const currentState: State = { }

// Counts - suffix with 'Count'
const userCount = users.length
const retryCount = 0
const errorCount = errors.length

// IDs - suffix with 'Id'
const userId = '123'
const orderId = 'abc'
const sessionId = 'xyz'

// Refs - suffix with 'Ref'
const inputRef = useRef<HTMLInputElement>(null)
const containerRef = useRef<HTMLDivElement>(null)

// Timeouts/Intervals - suffix with 'Timeout' or 'Interval'
const fetchTimeout = setTimeout(() => { }, 1000)
const pollingInterval = setInterval(() => { }, 5000)
```

### Constants

```typescript
// API endpoints
const API_BASE_URL = 'https://api.example.com'
const AUTH_ENDPOINT = '/auth/login'
const USERS_ENDPOINT = '/users'

// Configuration values
const MAX_RETRY_ATTEMPTS = 3
const DEFAULT_PAGE_SIZE = 20
const SESSION_TIMEOUT_MS = 30 * 60 * 1000

// Feature flags
const FEATURE_NEW_CHECKOUT = 'feature_new_checkout'
const FEATURE_DARK_MODE = 'feature_dark_mode'

// Error messages
const ERROR_NETWORK_FAILURE = 'Network request failed'
const ERROR_UNAUTHORIZED = 'You are not authorized'

// Validation rules
const MIN_PASSWORD_LENGTH = 8
const MAX_USERNAME_LENGTH = 50
const ALLOWED_FILE_TYPES = ['image/png', 'image/jpeg']
```

### Types and Interfaces

```typescript
// Entity types - noun
interface User {
  id: string
  email: string
  name: string
}

interface Product {
  id: string
  name: string
  price: number
}

// Props interfaces - ComponentName + 'Props'
interface UserProfileProps {
  userId: string
  onEdit?: () => void
}

interface ButtonProps {
  variant?: 'primary' | 'secondary'
  size?: 'sm' | 'md' | 'lg'
}

// State types - context + 'State'
interface AuthState {
  user: User | null
  isAuthenticated: boolean
}

interface FormState {
  values: Record<string, any>
  errors: Record<string, string>
}

// Action types - context + 'Action'
type AuthAction =
  | { type: 'LOGIN'; payload: User }
  | { type: 'LOGOUT' }
  | { type: 'UPDATE_USER'; payload: Partial<User> }

// Response types - endpoint + 'Response'
interface LoginResponse {
  user: User
  token: string
}

interface UsersResponse {
  users: User[]
  total: number
  page: number
}

// Request types - endpoint + 'Request'
interface LoginRequest {
  email: string
  password: string
}

interface CreateUserRequest {
  email: string
  name: string
  role: UserRole
}

// Union types - descriptive of options
type ButtonVariant = 'primary' | 'secondary' | 'danger'
type LoadingState = 'idle' | 'loading' | 'success' | 'error'
type SortDirection = 'asc' | 'desc'
```

### Enums

```typescript
// Enum name - PascalCase
// Enum values - UPPER_SNAKE_CASE
enum UserRole {
  ADMIN = 'ADMIN',
  MODERATOR = 'MODERATOR',
  USER = 'USER',
  GUEST = 'GUEST',
}

enum OrderStatus {
  PENDING = 'PENDING',
  PROCESSING = 'PROCESSING',
  SHIPPED = 'SHIPPED',
  DELIVERED = 'DELIVERED',
  CANCELLED = 'CANCELLED',
}

enum HttpMethod {
  GET = 'GET',
  POST = 'POST',
  PUT = 'PUT',
  PATCH = 'PATCH',
  DELETE = 'DELETE',
}
```

### File Naming

```
components/
├── UserProfile/
│   ├── index.tsx              # Main export
│   ├── UserProfile.tsx        # Component
│   ├── UserProfile.test.tsx   # Tests
│   ├── UserProfile.styles.ts  # Styles (if needed)
│   └── types.ts               # Local types
├── ui/
│   ├── Button.tsx
│   ├── Card.tsx
│   └── Input.tsx
hooks/
├── useAuth.ts
├── useLocalStorage.ts
└── usePagination.ts
lib/
├── api/
│   ├── client.ts
│   ├── endpoints.ts
│   └── types.ts
├── utils/
│   ├── formatDate.ts
│   ├── validateEmail.ts
│   └── index.ts
└── constants/
    ├── apiRoutes.ts
    ├── errorMessages.ts
    └── index.ts
```

## Anti-Patterns to Avoid

```typescript
// DON'T: Hungarian notation
const strName = 'John'        // Bad
const name = 'John'           // Good

// DON'T: Abbreviations (except common ones)
const usr = getUser()         // Bad
const user = getUser()        // Good
const idx = items.findIndex() // Acceptable (common)

// DON'T: Single letter variables (except loops)
const d = new Date()          // Bad
const currentDate = new Date() // Good
for (let i = 0; i < 10; i++)  // Acceptable in loops

// DON'T: Prefix interfaces with 'I'
interface IUser { }           // Bad (not idiomatic in TS)
interface User { }            // Good

// DON'T: Type suffix on types
type UserType = { }           // Bad
type User = { }               // Good

// DON'T: Redundant context
class UserClass { }           // Bad
class User { }                // Good

// DON'T: Negative boolean names
const isNotValid = false      // Bad
const isInvalid = false       // Acceptable
const isValid = true          // Better
```

## Domain-Specific Conventions

For this project (financial/educational platform):

```typescript
// Credit/Payment related
interface CreditCard { }
interface PaymentMethod { }
function calculateEMI() { }
function validatePAN() { }

// Course/Lesson related
interface Course { }
interface Lesson { }
interface LessonProgress { }
function markLessonComplete() { }

// User/Auth related
interface UserProfile { }
interface AuthToken { }
function refreshAuthToken() { }
```

```

wednesday-dev | SkillHub