Structuring the dona-ana-backend: Initializing with Strapi and Hexagonal Architecture
Foundation
We have officially kicked off the development of the dona-ana-backend project. Our goal is to create a robust and maintainable API service that can grow alongside our requirements. To achieve this, we have decided to utilize Strapi as our content management foundation, wrapped in a Hexagonal Architecture pattern.
The Challenge
Starting a new project often brings the temptation to tightly couple business logic with the framework's database layer. However, we recognized two potential bottlenecks early on:
- Framework Lock-in: Directly embedding complex business rules into Strapi controllers makes them hard to test and migrate later.
- Scalability Concerns: As the project evolves, we want to ensure our core domain logic remains isolated from our infrastructure (database, API endpoints).
The Strategy
To address this, we are enforcing a strict separation of concerns. By adopting Hexagonal Architecture (or "Ports and Adapters"), we treat Strapi as an infrastructure adapter rather than the application core.
Here is a conceptual look at how we structure our service layers:
// Domain Layer: Pure business logic, framework-agnostic
interface UserDomain {
id: string;
name: string;
}
// Infrastructure Layer: The Strapi adapter
class UserStrapiAdapter {
async findOne(id: string): Promise<UserDomain> {
const entry = await strapi.db.query('api::user.user').findOne({ where: { id } });
return this.mapToDomain(entry);
}
private mapToDomain(data: any): UserDomain {
return { id: data.id, name: data.name };
}
}
Key Decisions
- Core Domain Independence: Business rules reside in pure TypeScript modules that have no knowledge of Strapi internals.
- Interface Ports: We define clear interfaces for data persistence, allowing us to swap or mock database providers during unit testing.
- Decoupled API Layer: Strapi controllers act strictly as thin entry points that delegate calls to our service interfaces.
Results
By establishing this structure at the "Version 0" stage, we have gained:
- Improved Testability: We can now test our business logic without spinning up the full Strapi runtime.
- Cleaner Maintenance: Refactoring the database structure no longer requires rewriting the business services.
Lessons Learned
Building with a modular mindset from the first commit is the best investment for long-term project health. Even when using a powerful framework like Strapi, keeping your domain code isolated ensures you remain in control of your application's architecture.
Takeaway: Start your next project by defining your business domain models before hooking them into any framework-specific controllers. This simple step forces you to clarify your logic before implementation details get in the way.
Generated with Gitvlg.com