Claude-skill-registry coding-standards
Universal coding standards and best practices for TypeScript, JavaScript, React, and Node.js. Use when: writing code, reviewing code quality, establishing conventions. Focuses on modern patterns, explicit conventions, and rationale for best practices.
git clone https://github.com/majiayu000/claude-skill-registry
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/attic" ~/.claude/skills/majiayu000-claude-skill-registry-coding-standards && rm -rf "$T"
skills/data/attic/SKILL.mdCoding Standards & Best Practices
Modern coding standards applicable across TypeScript, JavaScript, React, and Node.js projects.
Quick Navigation
| If you need... | MANDATORY READ WHEN... | File |
|---|---|---|
| Type patterns | WRITING TYPES | |
| React patterns | WRITING COMPONENTS | |
| API patterns | DESIGNING APIS | |
| Testing patterns | WRITING TESTS | |
Core Principles
1. Readability First
WHY: Code is read 10x more than written. Optimize for the reader.
Practices:
- Self-documenting code preferred over comments
- Descriptive variable and function names
- Consistent formatting (use linter/formatter)
- Clear intent over clever tricks
Recognition: "Would a new team member understand this without explanation?"
2. Immutability Pattern (CRITICAL)
WHY: Prevents stale closures, makes state predictable, enables React optimizations.
✅ ALWAYS use spread operator:
const updatedUser = { ...user, name: 'New Name' } const updatedArray = [...items, newItem]
❌ NEVER mutate directly:
user.name = 'New Name' // BAD - causes bugs items.push(newItem) // BAD - breaks React optimizations
Best practice: Use Lodash (cloneDeep), Immer, or structuredClone for deep objects.
3. Functional Updates for State
WHY: Prevents stale closure bugs in async scenarios.
✅ GOOD (functional update):
setCount(prev => prev + 1) setData(prev => ({ ...prev, field: value }))
❌ BAD (direct reference - can be stale):
setCount(count + 1) // May use stale value setData({ ...data, field: value }) // Can miss updates
4. Comprehensive Error Handling
WHY: Unhandled errors crash processes, cause bad UX, make debugging impossible.
✅ GOOD pattern:
async function fetchData(url: string) { try { const response = await fetch(url) if (!response.ok) { throw new Error(`HTTP ${response.status}: ${response.statusText}`) } return await response.json() } catch (error) { console.error('Fetch failed:', error) throw new Error('Failed to fetch data') } }
❌ BAD (no error handling):
async function fetchData(url) { const response = await fetch(url) return response.json() // Crashes on network failure }
5. Parallel Async Execution
WHY: Sequential awaits waste time. Parallel execution is faster.
✅ GOOD (parallel when possible):
const [users, markets, stats] = await Promise.all([ fetchUsers(), fetchMarkets(), fetchStats() ])
❌ BAD (sequential when unnecessary):
const users = await fetchUsers() // Waits 100ms const markets = await fetchMarkets() // Waits 100ms (total: 200ms) const stats = await fetchStats() // Waits 100ms (total: 300ms)
Recognition: "Can these operations run in parallel?" → Use Promise.all
6. Type Safety Over Convenience
WHY: Types catch bugs at compile-time, serve as documentation, enable refactoring.
✅ GOOD (proper types):
interface Market { id: string name: string status: 'active' | 'resolved' | 'closed' } function getMarket(id: string): Promise<Market> { }
❌ BAD (using
any):
function getMarket(id: any): Promise<any> { }
Recognition: "Could I use a more specific type?" → Always prefer specificity
Naming Conventions
Variables and Functions
✅ GOOD (descriptive, camelCase):
const marketSearchQuery = 'election' const isUserAuthenticated = true const totalRevenue = 1000 async function fetchMarketData(marketId: string) { } function calculateSimilarity(a: number[], b: number[]) { }
❌ BAD (unclear, abbreviated):
const q = 'election' const flag = true const x = 1000 async function market(id: string) { } function similarity(a, b) { }
Boolean Variables
Prefix with
, is
, has
, should
:can
const isLoading = true const hasPermission = false const shouldRetry = true const canEdit = true
Constants
Use UPPER_SNAKE_CASE for true constants (never reassigned):
const MAX_RETRIES = 3 const DEFAULT_TIMEOUT_MS = 5000 const API_BASE_URL = 'https://api.example.com'
Code Organization
File Structure Preference
src/ ├── components/ # React components │ ├── ui/ # Generic, reusable │ └── features/ # Feature-specific ├── hooks/ # Custom React hooks ├── lib/ # Utilities and helpers │ ├── api/ # API clients │ ├── utils/ # Helper functions │ └── constants/ # Constants ├── types/ # TypeScript types └── styles/ # Global styles
File Naming
| Type | Pattern | Example |
|---|---|---|
| Components | PascalCase | , |
| Hooks | camelCase with prefix | , |
| Utilities | camelCase | , |
| Types | camelCase with suffix | |
| Constants | camelCase with suffix | |
Common Anti-Patterns
Anti-Pattern 1: Magic Numbers
❌ BAD:
if (retryCount > 3) { } setTimeout(callback, 500)
✅ GOOD:
const MAX_RETRIES = 3 const DEBOUNCE_DELAY_MS = 500 if (retryCount > MAX_RETRIES) { } setTimeout(callback, DEBOUNCE_DELAY_MS)
Anti-Pattern 2: Deep Nesting
❌ BAD (5+ levels):
if (user) { if (user.isAdmin) { if (market) { if (market.isActive) { if (hasPermission) { // Do something } } } } }
✅ GOOD (early returns):
if (!user) return if (!user.isAdmin) return if (!market) return if (!market.isActive) return if (!hasPermission) return // Do something
Anti-Pattern 3: Console.log in Production
❌ BAD:
console.log('User logged in', user) console.error('Error occurred', error)
✅ GOOD:
// Use proper logging library logger.info('User logged in', { userId: user.id }) logger.error('Error occurred', { error, context })
Anti-Pattern 4: Ignoring Type Errors
❌ BAD:
// @ts-ignore const data = JSON.parse uncertain
✅ GOOD:
const data = JSON.parse uncertain as unknown as ExpectedType // Or use zod/joi for validation
Performance Best Practices
Memoization
Use for:
- Expensive computations (
)useMemo - Functions passed to children (
)useCallback - Pure components (
)React.memo
const sortedMarkets = useMemo(() => { return markets.sort((a, b) => b.volume - a.volume) }, [markets]) const handleSearch = useCallback((query: string) => { setSearchQuery(query) }, [])
Lazy Loading
Use for:
- Heavy components (
,lazy
)Suspense - Route-based code splitting
- Non-critical features
const HeavyChart = lazy(() => import('./HeavyChart')) <Suspense fallback={<ChartSkeleton />}> <HeavyChart data={data} /> </Suspense>
Verification Checklist
Before considering code complete:
- Immutability pattern used (spread operators)
- Functional state updates (prev => pattern)
- Comprehensive error handling
- Type-safe (no
without justification)any - Parallel async execution where possible
- Descriptive naming (self-documenting)
- No console.log in production code
- No magic numbers (use constants)
- Early returns over deep nesting
- Performance optimizations applied
Integration with Other Skills
This skill integrates with:
- React/Next.js specific patternsfrontend-patterns
- API and database patternsbackend-patterns
- Testing standardstdd-workflow
- Quality gate verificationverify
Recognition: "Am I following WHY-based best practices?" → If you're doing something "because that's how it's done," you're missing the rationale.