1---2name: software-principles3description: Engineering principles for all code in this Next.js JavaScript project. Required reading before any code generation.4license: MIT5---67## Pre-Code Checklist891. One reason to change? If not — split (SRP)102. Simpler solution, same outcome? — use it (KISS)113. Building for a future need that doesn't exist? — delete it (YAGNI)124. Name reveals intent without generic words (`and`, `data`, `info`, `manager`, `handle`)? If not — rethink design1314## Principles1516| Principle | Rule | Violation Signal | Fix |17| ------------------------------------ | --------------------------------- | -------------------------------------------------- | ------------------------------------------- |18| **SRP** — Single Responsibility | One unit, one reason to change | `"and"` in name · file > 200 lines · fn > 20 lines | Split into focused units |19| **OCP** — Open/Closed Principle | Extend without modifying existing | Adding variant by editing component internals | Variant props · composition · new component |20| **DIP** — Dependency Inversion | Depend on abstractions | `new ConcreteService()` hardcoded inside logic | Inject dependencies |21| **Composition > Inheritance** | Compose via hooks/props | Class chains | Props + custom hooks |22| **DRY** — Don't Repeat Yourself | One source of truth per logic | Copy-paste logic across files | Extract to shared fn/module |23| **KISS** — Keep It Simple, Stupid | Simplest correct solution | Unnecessary abstraction · deep indirection | Remove layers · flatten |24| **YAGNI** — You Aren't Gonna Need It | Build only what's needed now | Unused params · "might need later" code | Delete it |25| **SoC** — Separation of Concerns | Each module owns one concern | UI + fetch + logic in one file | Separate layers (page · hook · util) |26| **LoD** — Law of Demeter | Talk only to direct collaborators | `a.b.c.method()` chains | Add intermediate method |27| **Fail Fast** | Surface errors at earliest point | Silent catch · late validation | Validate at boundaries · throw early |28| **SSOT** — Single Source of Truth | One authoritative place per logic | Same validation in multiple layers | Centralize · import everywhere |2930## Naming3132Names must reveal intent. Generic names destroy readability.3334| Concept | Pattern | Good | Bad |35| ---------- | ----------------------- | ---------------------------------------------- | --------------------------------------- |36| Functions | verb phrase | `getUserById`, `validateEmail`, `hashPassword` | `handle`, `process`, `doStuff`, `run` |37| Booleans | `is`/`has`/`can` prefix | `isActive`, `hasPermission`, `canDelete` | `active`, `flag`, `check`, `status` |38| Variables | noun, specific | `userId`, `paginatedUsers`, `hashedPassword` | `data`, `result`, `info`, `temp`, `val` |39| Components | PascalCase noun | `UserCard`, `AuthGuard`, `ModalOverlay` | `usercard`, `myComponent`, `Comp1` |40| Hooks | `use` + verb phrase | `useAuth`, `useFetchUser`, `useFormValidation` | `authHook`, `userData`, `myHook` |41| Files | `[domain].[layer].js` | `user.service.js`, `auth.middleware.js` | `utils2.js`, `misc.js`, `helpers.js` |4243No abbreviations except: `id`, `req`, `res`, `err`, `ctx`. No single-letter names outside loop counters. Name length proportional to scope.4445## Function Design4647| Rule | Limit | When exceeded |48| --------------------- | ----------------------- | -------------------------------------------- |49| Single responsibility | One action per function | Split into smaller functions |50| Length | ≤ 20 lines | Extract inner logic to named helper |51| Parameters | ≤ 3 | Group into options object |52| Nesting | ≤ 2 levels deep | Extract or use early return (guard clause) |53| Return paths | Prefer single exit | Guard clauses at top, one `return` at bottom |5455## Applied to This Project5657| Principle | Concrete example |58| --------- | ----------------------------------------------------------------------------------------- |59| SRP | `UserCard` renders one user — fetch lives in `useUser` hook, not the component |60| SoC | Pages fetch · UI components render · hooks own logic — never mix |61| DRY | Shared types in `types/` · validation schema once in `validations/` |62| Fail Fast | `config/env.js` throws at startup if env vars missing · validate API response at boundary |63| SSOT | Error messages → `constants/errors.js` · API base URL → one config file |64| YAGNI | No global state until local state is proven insufficient |65| KISS | Component calls one hook — no multi-source data orchestration inside JSX |66| DIP | Components depend on hook interfaces, not fetch calls directly |6768## Async Error Handling6970- Catch only where you can meaningfully recover71- Never `catch` and return `null`/`undefined` — throw a typed error instead72- React: use error boundaries or `error.jsx` for UI-level recovery7374## Testing7576- Unit test pure functions and hooks in isolation77- Integration test at API route boundaries — not implementation details78- Mock external services only — don't mock what you own79- One assertion per test concept8081## Never Do8283- Name anything `data`, `result`, `info`, `temp`, `manager`, `handleX`, `processX`84- Functions > 20 lines · params > 3 · nesting > 2 — split or group85- Mutate state directly — always return new references (`{ ...prev, key: value }`, `[...arr, item]`)86- Business logic inside JSX or component body — extract to hook or utility