Clean Architecture in a React or Next.js application means keeping important business rules and use cases independent from UI rendering and vendor-specific data access—not adopting a folder tree mandated by the framework. Next.js supplies routing, rendering, and file conventions; your team decides how to organize features, domain logic, and infrastructure around them.
What Clean Architecture means in a Next.js app
Clean Architecture is an application-level approach: core rules and use cases should not depend directly on React components, route files, or a particular database or API vendor. UI and infrastructure can depend on those core rules, while the core remains comparatively stable when presentation or implementation details change.
As an Amazon Associate I earn from qualifying purchases.
Next.js is a React framework for full-stack web applications. Its App Router is file-system based and uses React features including Server Components, Suspense, and Server Functions, as the official App Router documentation describes. That routing model is a framework convention, not a complete domain architecture.
How should I structure a Next.js app?
Start with the framework’s route conventions, then group application code around the capabilities and rules your product actually has. The Next.js project-structure documentation describes app for the App Router, pages for the Pages Router, public for static assets, and src as an optional location. It does not require a domain, features, or infrastructure directory.
#1 Best Overall
One workable organization
src/
app/ # Routes, layouts, and framework entry points
features/
orders/ # A cohesive user capability
components/
application/ # Use cases or feature-level services
data/ # Feature-specific adapters when useful
domain/ # Stable business concepts, if justified
infrastructure/ # Shared external-system adapters, if useful
This is an option, not an official Next.js layout. A project can put these directories at the repository root instead of under src, or choose a different organization. Keep route files easy to find and avoid making teammates guess which folders are framework-defined and which reflect team choices.
Pages Router and existing applications
The same separation can be applied in a Pages Router application: retain its pages route conventions and organize feature or domain code separately as appropriate. You do not need to migrate routers to adopt the architectural principle. For new examples below, the App Router is the reference point.
Rank #2
- TypeScript implements a superset of syntax for strictly typed development, facilitating deep static analysis and enhanced development environment integration. The compiler translates source into standard script formats, ensuring parity across any runtime.
- TypeScript is ideal for front-end developers, full-stack engineers, and software architects who build large-scale web applications. It serves those looking to improve code excellence, reduce bugs through static checking, and maintain complex projects more.
- Lightweight, Classic fit, Double-needle sleeve and bottom hem
Where should business logic go in a React app?
Put business rules and meaningful use cases in code that can be called without rendering a component. Put React-specific presentation and interaction in components. Route entry points should translate framework inputs into application calls and translate results into route UI, rather than becoming the home for every rule.
- Adapt route input. Read route parameters or other framework request data in the route entry point and validate inputs at the boundary.
- Call application behavior. Invoke a use case or feature service with the values it needs. It should express an outcome such as placing an order, not how a particular page is rendered.
- Use infrastructure through a deliberate seam. A feature service can call a data adapter or other integration where that separation makes the dependency replaceable or testable.
- Map results to UI. The page or feature component presents the result; interactive controls and local presentation state stay in React components.
A route can remain small without creating a class, repository, port, and use case for every screen. Add a layer when it isolates a real business rule, replaceable dependency, or useful testing seam. For a small feature with little logic, a direct and readable implementation can be easier to maintain than extra indirection.
Choosing Server and Client Components
In the App Router, layouts and pages are Server Components by default. The Next.js Server and Client Components guide describes Server Components as suitable for data access near its source, protected secrets, reducing JavaScript sent to the browser, and streaming. Client Components are appropriate when a unit needs state, event handlers, effects, browser-only APIs, or custom hooks. This is a capability decision, not a rule that one side is always better.
| Question | Lean toward a Server Component when | Use a Client Component when |
|---|---|---|
| Does it need browser interaction? | The UI can be rendered from data without browser-side state or event handlers. | It needs state, event handlers, effects, custom hooks, or browser APIs. |
| Does it access protected data? | It can fetch near the data source and keep secrets on the server. | It only needs the specific data passed to it for browser interaction. |
| What is the client JavaScript cost? | Keeping rendering on the server avoids adding that component’s module graph to the client bundle. | The interactive behavior warrants client-side code. |
| How does data cross the boundary? | The data can stay server-side or be reduced to the values the UI needs. | Pass only the data needed for client-side presentation and interaction. |
| Does the rendering experience fit? | Server rendering or progressive streaming suits the feature. | The required experience depends on browser-side behavior. |
Keep the client boundary close to interaction
The use client directive declares a module-graph boundary: modules imported beneath that entry point become part of the client bundle. Put it as close as practical to the interactive behavior instead of marking an entire route client-side merely because one control needs state. Plan deliberately which data crosses that boundary, and do not send secrets or unnecessary server data to client UI.
Use TypeScript at boundaries, and validate untrusted data
Next.js documents built-in TypeScript setup and checking, a custom TypeScript plugin, route-aware type helpers, and support for async Server Components in its TypeScript documentation. These are framework capabilities; they do not make every business rule or external payload automatically safe.
Make types explicit as values move from route input to application logic, infrastructure, and UI. Treat network responses and other external inputs as untrusted: pair compile-time types with runtime validation before relying on the received shape. A TypeScript annotation describes what code expects; it does not verify what a remote system actually returned.
Best Value
Use layouts and pages for their distinct route roles
In the App Router, a page file provides UI for a route, while a layout provides shared UI and persists across navigation. The layouts and pages guide explains these roles. A layout is a natural place for shared route-level UI; a page is the route-specific entry point. Neither convention requires business logic to live in those files: keep application behavior in an appropriate feature or service when doing so makes responsibilities clearer.
How much architecture does a frontend need?
Choose structure according to the complexity and change patterns of the application. Colocate code when it changes together and belongs to one capability. Extract shared abstractions when multiple features genuinely reuse a rule or adapter, or when isolation improves testing and replacement. Keep dependencies pointing toward business rules rather than making those rules depend on React rendering or a particular vendor integration.
- Small app or simple screen: use a few clear modules and avoid layers whose only purpose is forwarding calls.
- Growing feature: group its UI and behavior together so changes have an obvious home.
- Meaningful domain rules: separate stable business concepts from presentation and infrastructure where that separation reduces coupling.
- Replaceable or hard-to-test integration: introduce an adapter or interface when it creates a practical seam, not just to complete a diagram.
There is no universal winning folder layout or numerical threshold for when a component should move to the client. Revisit the organization when dependencies become difficult to follow, rules are duplicated, or testing a behavior requires too much framework or infrastructure setup.
Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




