Software principles
Skill hilmifawwazsaad/NextJS-js-Boilerplate/.agents/software-principles
Engineering principles for all code in this Next.js JavaScript project. Required reading before any code generation.From its SKILL.md
npx -y skills add hilmifawwazsaad/NextJS-js-Boilerplate --skill software-principlesAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its file declares
Copied from the file, not written here
The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.
SKILL.md
6.6 KB, ~1.3k tokens by cl100k_base, as published. Nobody here has run it
Pre-Code Checklist
- One reason to change? If not — split (SRP)
- Simpler solution, same outcome? — use it (KISS)
- Building for a future need that doesn't exist? — delete it (YAGNI)
- Name reveals intent without generic words (
and,data,info,manager,handle)? If not — rethink design
Principles
| Principle | Rule | Violation Signal | Fix |
|---|---|---|---|
| SRP — Single Responsibility | One unit, one reason to change | "and" in name · file > 200 lines · fn > 20 lines | Split into focused units |
| OCP — Open/Closed Principle | Extend without modifying existing | Adding variant by editing component internals | Variant props · composition · new component |
| DIP — Dependency Inversion | Depend on abstractions | new ConcreteService() hardcoded inside logic | Inject dependencies |
| Composition > Inheritance | Compose via hooks/props | Class chains | Props + custom hooks |
| DRY — Don't Repeat Yourself | One source of truth per logic | Copy-paste logic across files | Extract to shared fn/module |
| KISS — Keep It Simple, Stupid | Simplest correct solution | Unnecessary abstraction · deep indirection | Remove layers · flatten |
| YAGNI — You Aren't Gonna Need It | Build only what's needed now | Unused params · "might need later" code | Delete it |
| SoC — Separation of Concerns | Each module owns one concern | UI + fetch + logic in one file | Separate layers (page · hook · util) |
| LoD — Law of Demeter | Talk only to direct collaborators | a.b.c.method() chains | Add intermediate method |
| Fail Fast | Surface errors at earliest point | Silent catch · late validation | Validate at boundaries · throw early |
| SSOT — Single Source of Truth | One authoritative place per logic | Same validation in multiple layers | Centralize · import everywhere |
Naming
Names must reveal intent. Generic names destroy readability.
| Concept | Pattern | Good | Bad |
|---|---|---|---|
| Functions | verb phrase | getUserById, validateEmail, hashPassword | handle, process, doStuff, run |
| Booleans | is/has/can prefix | isActive, hasPermission, canDelete | active, flag, check, status |
| Variables | noun, specific | userId, paginatedUsers, hashedPassword | data, result, info, temp, val |
| Components | PascalCase noun | UserCard, AuthGuard, ModalOverlay | usercard, myComponent, Comp1 |
| Hooks | use + verb phrase | useAuth, useFetchUser, useFormValidation | authHook, userData, myHook |
| Files | [domain].[layer].js | user.service.js, auth.middleware.js | utils2.js, misc.js, helpers.js |
No abbreviations except: id, req, res, err, ctx. No single-letter names outside loop counters. Name length proportional to scope.
Function Design
| Rule | Limit | When exceeded |
|---|---|---|
| Single responsibility | One action per function | Split into smaller functions |
| Length | ≤ 20 lines | Extract inner logic to named helper |
| Parameters | ≤ 3 | Group into options object |
| Nesting | ≤ 2 levels deep | Extract or use early return (guard clause) |
| Return paths | Prefer single exit | Guard clauses at top, one return at bottom |
Applied to This Project
| Principle | Concrete example |
|---|---|
| SRP | UserCard renders one user — fetch lives in useUser hook, not the component |
| SoC | Pages fetch · UI components render · hooks own logic — never mix |
| DRY | Shared types in types/ · validation schema once in validations/ |
| Fail Fast | config/env.js throws at startup if env vars missing · validate API response at boundary |
| SSOT | Error messages → constants/errors.js · API base URL → one config file |
| YAGNI | No global state until local state is proven insufficient |
| KISS | Component calls one hook — no multi-source data orchestration inside JSX |
| DIP | Components depend on hook interfaces, not fetch calls directly |
Async Error Handling
- Catch only where you can meaningfully recover
- Never
catchand returnnull/undefined— throw a typed error instead - React: use error boundaries or
error.jsxfor UI-level recovery
Testing
- Unit test pure functions and hooks in isolation
- Integration test at API route boundaries — not implementation details
- Mock external services only — don't mock what you own
- One assertion per test concept
Never Do
- Name anything
data,result,info,temp,manager,handleX,processX - Functions > 20 lines · params > 3 · nesting > 2 — split or group
- Mutate state directly — always return new references (
{ ...prev, key: value },[...arr, item]) - Business logic inside JSX or component body — extract to hook or utility
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.