When we talk about modularization, it's common to see confusion with terms like componentization, especially among frontend developers using Vue, React, or similar frameworks. Components are reusable parts of the UI, but modularization goes far beyond that — it's about organizing and structuring the application as a whole, with the goal of separating responsibilities, isolating functionalities, and enabling greater scalability and maintainability.

So, What Exactly Is a Module?

In modern development, virtually every language has some form of package manager: NPM for Node.js, Composer for PHP, Cargo for Rust, and so on. All of them rely on the concept of modules — independent libraries that encapsulate specific functionalities, like sending emails, connecting to databases, or running an HTTP server.

However, when you start combining multiple modules that interact with each other, each with clearly defined responsibilities and a coherent architecture, you’re approaching what many call a framework.

A good example is NestJS, which has a lean core and various optional modules like authentication, caching, mailing, etc. The community can also contribute its own modules. Still, even with such modular architecture, we’re talking about modules within the same ecosystem — not necessarily a truly modular and agnostic application in a broader sense.

Modularization in Practice

While developing the blog plugin you’re using to read this post, I chose an approach based on my own framework: CMMV.

Unlike traditional frameworks, CMMV is not just a backend or REST API solution — it's a complete application ecosystem, covering backend, frontend, binary communication (RPC), and integration with multiple languages through the core concept of contracts.

These contracts are not limited to JavaScript or TypeScript — even though the core is built around them — and are also used in environments like C++ for game development. The main goal is to create agnostic, reusable modules that can be consumed by any technology, as long as they follow the established contract.

The Blog Case

This blog system is the first full-stack plugin developed using CMMV. It’s not just an API — it includes:

  • An administrative dashboard

  • A decoupled API

  • An SDK that encapsulates all communication logic

  • Support for multiple frontends

Initially, I built the frontend using Vue 3, but because the SDK follows an agnostic call pattern (no Axios, no direct Fetch), it was easy to port it to React, Angular, and even pure JavaScript. That means any modern language (like Go, Dart/Flutter, etc.) can be used to build a frontend or mobile app without rewriting the API logic.

The only part that’s somewhat coupled is the contract layer, which is defined in TypeScript by default. However, these contracts can be translated to other languages — and that’s the key point: true modularization allows natural extensibility, without forcing rewrites or tight coupling.

SDK as a Universal Bridge

One of the most important decisions in the design of CMMV was to use SDKs as an abstraction layer, instead of just exposing REST endpoints and leaving consumption to the frontend.

The SDK defines how data should be processed, interpreted, and displayed, ensuring consistency across environments.

This model is very similar to what companies like Supabase and AWS use: robust backends with multi-language SDKs that abstract complexity and standardize API usage in different ecosystems.

Monorepo and Scalability

Another key architectural choice was to use a monorepo, orchestrated with TurboRepo, to manage multiple packages. This allows for:

  • Code sharing between backend, frontend, and SDKs

  • Isolated and optimized builds

  • Better control over versioning, caching, and builds

TurboRepo, maintained by the Next.js team, is one of the best solutions available for growing multi-package projects. Other tools, like NPM workspaces, also support this kind of architecture and are equally valuable.

This approach is already adopted by projects like Supabase, N8N, and many others.

Conclusion

Modularizing an application goes far beyond creating folders or splitting files. It’s about defining clear boundaries of responsibility, creating abstractions that communicate well across environments, and maintaining the flexibility to evolve or refactor parts of the system without breaking everything.

If you’re building a modern system, consider:

  • Creating SDKs to encapsulate API communication

  • Using monorepos with tools like TurboRepo

  • Investing in strong, reusable contracts

  • Separating UI and business logic clearly

It might feel like extra effort at first, but in the long run, it will give you scalability, reusability, and technological freedom.