Table of Contents
Overview
API URLs, versions, and endpoints are among the most volatile parts of any application. Since they depend on external services, frequent changes can quickly lead to:
- Spaghetti code (scattered URL strings)
- Brittle integrations (tight coupling with third-party APIs)
- Maintenance nightmares (manual updates across files)
This architecture solves those problems by:
- Centralizing endpoint logic in dedicated classes.
- Abstracting URL construction behind reusable methods.
- Isolating versioning/base URLs for easy updates.
Result: Your core code stays clean, even when APIs change.
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…
Endpoints architecture
The following class diagram shows the architecture of endpoints:
Endpoints explanations
BaseEndpoint:
The BaseEndpoint class is implemented for manipulating API endpoints within an application.
the BaseEndpoint class requires two parameters: baseURL
and apiVersion
, which represent the base URL of the API and the version of the API being used.
BaseEndpoint class has several methods:
-
compose Method (Static)
This static method, takes an array of strings representing different parts of the URL and returns a sanitized URL by joining these parts together. It ensures that the URL is properly formatted and free of any unnecessary double slashes or incorrect separators. -
buildEndpoint Method
This instance method, buildEndpoint, is responsible for constructing a complete endpoint URL by appending a specific endpoint to the base URL and API version. It returns a sanitized URL string ready for use in API requests. -
sanitizeURL Method (Static)
You can use this method to ensure that the constructed URLs are correctly formatted. It replaces any occurrences of consecutive slashes with a single slash, ensuring that the URL is valid and compliant with URL standards.
Overall, The BaseEndpoint
class offers a convenient and reliable way to construct and manage endpoint URLs within an application. It enables team members to use a shared language when working with third-party libraries, reducing the risk of bloating the main application code due to API or UI changes in external dependencies.
SpecificEndpoint
Every specific endpoint class extends the functionality of the BaseEndpoint
class and introduces additional features specific to this specific endpoint. This inheritance includes methods for composing and building endpoint URLs.
The specific endpoint encapsulates private properties, these properties are URLs for a specific endpoint.
Overall, the SpecificEndpoint
class extends the capabilities of the BaseEndpoint class by adding specific endpoint functionalities tailored to the specific system. It provides a convenient and centralized approach for managing and accessing Specific-related endpoints within the application. The following is an example about making a specific endpoint and how it extends the base endpoint:
import BaseEndpoint from "~/bootstrap/helper/endpoint/base-endpoint";
export default class BookEndpoint extends BaseEndpoint {
private addBookEndpoint: string;
private booksEndpoint: string;
get addBook() {
return this.buildEndpoint(this.addBookEndpoint);
}
get books() {
return this.buildEndpoint(this.booksEndpoint);
}
constructor({
addBookEndpoint,
booksEndpoint,
baseURL,
apiVersion,
}: {
addBookEndpoint: string;
booksEndpoint: string;
baseURL: string;
apiVersion: string;
}) {
super({
apiVersion,
baseURL,
});
this.addBookEndpoint = addBookEndpoint;
this.booksEndpoint = booksEndpoint;
}
}
As you see the BookEndpoint class extends BaseEndpoint to provide a structured way of managing book-related API endpoints. It encapsulates endpoint construction logic, ensuring consistency and reusability across the application.
EndpointsProvider
The EndpointsProvider class offers centralized static methods for retrieving various endpoints used in the application. Each method returns an instance of a specific endpoint class, preconfigured with the necessary URLs and settings.
By encapsulating the logic for creating and configuring endpoints, this class simplifies access and usage across the application. Below is an example of how the EndpointsProvider works:
import BookEndpoint from "~/bootstrap/helper/endpoint/endpoints/book-endpoints";
import appConfigs from "~/bootstrap/config/app-configs";
/**
* Provides static methods to retrieve different types of endpoints.
*/
export default class EndpointsProvider {
/**
* Book api
*/
static book() {
return new BookEndpoint({
apiVersion: "api/v1",
addBookEndpoint: "book/add",
booksEndpoint: "book",
baseURL: appConfigs.baseApis.book,
});
}
}
Note: The EndpointProvider step is optional. Instead, you can statically define all required endpoint configurations directly in the endpoint class's constructor.
Usage Example
You can see implementation examples in this Next.js boilerplate:
Endpoint Files
-
Endpoint implementations
Contains two endpoint types:
- HTTP backend API connections
- Identity provider API connections
Implementation
- Repository usage Demonstrates how backend endpoints are consumed throughout the application
Conclusion
Managing API endpoints effectively is crucial for building maintainable applications in our API-driven world. The architecture we've explored:
✅ Isolates volatile API configurations from business logic
✅ Standardizes endpoint management across your codebase
✅ Dramatically reduces tech debt when APIs inevitably change
By implementing this pattern, you'll spend less time on finding and fixing broken endpoints and more time building features.
Remember: Good architecture isn't about preventing change - it's about making change manageable.
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!