Table of Contents
- Table of Contents
- Clean Architecture Overview
- Why did We choose Clean Architecture?
- Project clean architecture diagram
- Layers breaking down
- Layers Connection
- Folder structuring
-
Conclusion
Clean Architecture Overview
Clean Architecture is a software design philosophy that promotes structuring of large scale systems with a strong emphasis on separation of concerns and dependency inversion. The main goal is to create systems that are highly maintainable, scalable, and testable, while ensuring business logic remains isolated and independent of external frameworks and tools.
Note: for reading more information about clean architecture visit this link
Why did We choose Clean Architecture?
For large-scale projects that contains multiple domains characterized by tight coupling between them. Furthermore, these domains can be extended with new features without any predicted limitations.
Therefore, we require an architecture that can support, scalability, single responsibility, maintainability, testability and quality assurance. Also we need a shared language for our big system which is understandable among the team members.
Implementing a clean architecture, customized to accommodate frontend-specific features, was the optimal solution for this issue.
Project clean architecture diagram
As we discussed we used customized version of clean architecture based on nextjs-specific features.
This article based on Next.js boilerplate repository.
To explore all concepts in depth and see a production-ready boilerplate and following these best practices, visit:
behnamrhp / Next-clean-boilerplate
A Full featured nextjs boilerplate, based on clean architecture, mvvm and functional programming paradigm.
Nextjs clean architecture boilerplate
Table of content
- Overview
- Technologies
- Architecture
- Folder Structure
- Getting started
- Guildline
Overview
This project is a starting point for your medium to large scale projects with Nextjs, to make sure having a structured, maintainable and reusable base for your project based on best practices in clean architecture, DDD approach for business logics, MVVM for the frontend part, storybook and vitest for testing logics and ui part and also functional programming with error handling for business logics.
Motivation
Nextjs and many other new SSR tools provide a really good and new approach to handle frontend applications, with new tools to bring a new good experience for users. But as they're new and they just tried to bring new tools and features and also frontend community, didn't talk about software engineering and best practices approach for this tools.
So in many cases we see many teams uses nextjs…
Layers breaking down
Application Layer
This layer is responsible for handling framework and tools, also it'll connect directly to the user.
This Layer is based on MVVM (Model-ViewModel-View) Architecture.
This architecture Helps us separate the business logics (controller), UI logics (ViewModel) and UI (View).
To decrease the size of the article we separated application layer document to a separated document.
For application layer concepts visit this doc and also article which we mentioned inside of it to get master at MVVM in react based projects:
application layer architecture
Feature Layer
This layer responsibles for just business logics.
Domain
This layer is a part of Feature layer which is the heart of our app and it just care about the main business logics of the app.
So This layer is independent of any specific technology or framework and represent the fundamental concepts and rules of the business domain.
This layer contains three parts:
-
Entity: Is our business object and contains our business rules.
Example: `User` entity represents: - `id` - `firstName` - `lastname` - Also some business object logics like `getFullName`
-
Usecase: The Use Case represents the main business logic of the application and orchestrates the overall process flow. It interacts with entities and communicates with external systems through repositories (IRepository).
In this scenario, the primary benefit is the separation of core business logic from external frameworks and third-party dependencies, ensuring encapsulation and maintainability of the application.Example:
In an e-commerce application:
PlaceOrderUseCase
:
Manages the process of placing an order, including validation, inventory management, and order creation.
Utilizes IProductRepository to retrieve and update product information without directly coupling to the database or external APIs. I-Repository: It's an interface to define a contract for data access operations within the application. It abstracts away the details of specific data storage implementations (such as databases or external services) from the usecase.
-
So our usecase knows how to communicate with outside of the app through I-Repository.
Data
This layer is responsible for interfacing with external systems and services, adapting their data formats and logic into business entities that the application can use.
- Repository: It implements the
IRepository
interface defined in the domain layer. It serves as a bridge for managing data format adaptation between the application's business entities and external data sources. In essence, the Repository acts as an adapter between use cases and external services.
This repository uses Mapper
to turn data format between application business entities and datasources.
Note: For more details about feature layer, class diagram, code example, testing of this layers, you can visit this document:
feature layer architecture
Bootstrap layer
Bootstrap layer represents configs and initial configuration of application. It includes DI configuration, localization configuration, configuration for graphql, httpHandled and local storage, base classes for context, view and vm.
It has these folders:
- boundary - to implement library boundary.
- config - configuration for application.
- di - DI configuration.
- global-types - typescript types to be used in any place of project.
- helper - place for extract frequently encoutered functions, classes and types.
- i18n - localization configuration.
Layers Connection
For connecting layers we uses DI(dependency-injection) by tsyringe.
Note: Fore more details about DI, Structures and usage examples, please visit DI documentation from How We Fixed Next.js at Scale: DI & Clean Architecture Secrets From Production
Folder structuring
└── src/
├── app/
│ └── users/
│ ├── controllers
│ ├── view/
│ │ ├── server
│ │ └── client/
│ │ └── some-component/
│ │ ├── some-component.view.tsx
│ │ ├── stories
│ │ └── style/
│ │ └── i-vm
│ ├── page
│ └── vm
├── feature/
│ ├── core/
│ │ └── users/
│ │ ├── data/
│ │ │ ├── repository
│ │ │ └── mapper
│ │ └── domain/
│ │ ├── failure
│ │ ├── i-repository
│ │ ├── entity
│ │ └── usecase
│ ├── support
│ └── generic
├── bootstrap/
│ ├── boundary
│ ├── config/
│ │ ├── server
│ │ └── client
│ ├── di
│ ├── endpoint
│ ├── helper
│ └── i18n
└── test/
├── common
├── unit
└── e2e
DDD aproach in folder structuring
For folder structuting we can following Domain Driven Design approach. A domain is a subject area that describes a set of business problems and goals. We have 3 domains in our project
- core - all the features that are related to the main purpose of the project.
- generic - reusable logic to use in any place from project.
- support - logic that helps to perform logic.
Each one of them has subdomains for separate feature.
For example for buisness layer of User feature we will go inside of src/features/core/user
.
Conclusion
Clean Architecture in Next.js ensures a scalable, maintainable, and testable codebase by separating concerns into distinct layers: Application (UI), Feature (business logic), and Bootstrap (configurations).
Why It Works:
Decoupled Logic – Business rules stay independent of frameworks.
Easy Testing – Isolated layers simplify unit and integration tests.
Flexible Growth – Features can expand without tight coupling.
By using Dependency Injection and Domain-Driven Design, teams can collaborate efficiently while keeping the codebase clean and adaptable.
If you found this article helpful, I’d be truly grateful if you could:
⭐ Star the repository to support its visibility
💬 Share your thoughts in the comments—your feedback helps improve content reach
Every interaction helps these best practices reach more developers!