Skill for implementing features, pages, API routes, and business logic in a NextJS application following SOLID principles, clean code practices, and the project's architectural conventions.
When to use
When you need to:
Create or refactor pages, components, API routes, or services.
Implement new features end-to-end (UI, logic, data layer).
Ensure code follows SOLID principles and project conventions defined in AGENTS.md.
SOLID principles applied to NextJS
S — Single Responsibility Principle
Each file, component, hook, or service must have one clear responsibility.
A page component (page.tsx) should only orchestrate layout and data fetching. Business logic must live in services or hooks.
A component should either fetch data (container) OR render UI (presentational), never both.
O — Open/Closed Principle
Components and services should be open for extension but closed for modification.
Use composition over inheritance: extend behavior by wrapping or composing components, not by modifying existing ones.
Use props and slots (children, render props) to extend UI components without rewriting them.
L — Liskov Substitution Principle
DTOs implementing interfaces must fulfill the interface contract completely.
Any component receiving an interface-typed prop must work correctly with any class implementing that interface.
Avoid adding extra required dependencies in subclasses or implementations that break the abstraction.
I — Interface Segregation Principle
Define narrow, focused interfaces. Do not force a component or class to depend on methods/props it does not use.
Split large interfaces into smaller ones if a consumer only needs a subset.
Example: separate ReadableRepositoryInterface from WritableRepositoryInterface instead of one monolithic RepositoryInterface.
D — Dependency Inversion Principle
High-level modules (pages, containers) should depend on abstractions (interfaces), not concrete implementations.
Inject dependencies (services, repositories) through props, context, or constructor arguments rather than instantiating them directly inside the consumer.
Use React Context or dependency injection patterns to provide implementations to consumers.
Code conventions (from AGENTS.md)
File & folder structure
Pages live in app/pages/<feature>/page.tsx.
Each page has its own scaffolding: components/, styles/, dtos/, services/, utils/, etc.
services/ contains business logic and data-access functions (e.g. sectionService.ts, debtService.ts).
utils/ contains pure helper/formatting functions with no side effects or data-access concerns.
Shared/reusable components live outside pages/, in a shared/ or components/ root folder.
Container / Presentational pattern
Container : responsible for data fetching, state, and business logic. Passes data to presentational components via props.
Presentational : responsible only for rendering UI. Receives all data via props. Must be stateless when possible.
Instructions
When creating a new feature end-to-end:
Understand the feature requirements and identify all responsibilities involved (UI, data fetching, business logic, persistence).
Define interfaces for each data entity and service involved. Place them in the dtos/ folder.
Create DTO classes implementing those interfaces.
Implement service functions or classes for business logic. Each service has a single responsibility (SRP).
Create the container component that fetches data and orchestrates logic.
Create presentational components that receive data via props and only render UI.
Wire everything together in the page.tsx file.
Ensure no component directly depends on a concrete data-fetching implementation — use abstractions or hooks.
When refactoring existing code:
Identify violations of SOLID principles (mixed responsibilities, direct concrete dependencies, large interfaces).
Extract business logic into dedicated service files or custom hooks.
Split components that are doing both data fetching and rendering into container + presentational pairs.
Replace concrete dependencies with interface-typed abstractions where applicable.
Verify all DTOs correctly implement their interfaces.
When creating API routes:
Each API route file handles one resource and one HTTP concern (SRP).
Validate input at the boundary (API route level) using DTOs or validation schemas.
Delegate business logic to service functions — never inline it in the route handler.
Return consistent response shapes; define response DTOs if needed.