Architecture
Modular
Decoupling
Layer

Architectures of modern Front-end applications

Dmitry BobryshevDmitry Bobryshev
7 min read
undefined

Business requirements can be different and change frequently in the process, so it’s important to create an architecture that is flexiblescalable and maintainable. It’s also key that everyone, like team members and clients, understands the project clearly. To avoid extensive documentation, frequent meetings, and continuous refinements, we employ the following architectural approaches. This post explores the advantages of popular architectures and helps you choose the best solution to meet your unique requirements.


A lot of people think that the architectures listed below are just “folder structures”, which is only kind of true. In fact, if you look deeper into them, there are several important aspects:

  • Modular Cooperation: Efficient communication and interaction between different modules/components in the app (using component-based architecture, reusable code).
  • Improved Project Navigation: Structuring the project in a way that makes it easy to navigate and maintain (clear folder hierarchy, naming conventions, separation of concerns).
  • Separation of Business Logic from UI Components: Keeping the business logic (data fetching, state management) separate from the UI components to improve maintainability and reusability (e.g., using services or stores like Redux, Context API).
  • DRY: Don’t repeat yourself
  • DAC: Divide and conquer

Take a look at the following diagram — we’re focusing on the area in the bottom right corner, where these principles come together most effectively:

Architectures #1

We want to realize these aspects with the help of architectures. Now let’s analyze each of them in detail and choose the most relevant one for a specific situation.


Classic architecture (without architecture)

Classic architecture — is an approach that many of you already use. We usually focus on basic concepts, dividing the project into “pages”“components”“ helpers” and so on. However, the problem is that as the application grows, the structure starts to break down and it becomes much harder to find the right component or its business logic. Let’s look at this with an example:

Architectures #2

In this example, we have 3 pages that are obviously not overused. However, they may include all the components shown below. If we look at these components, we see a real “chaos” 🤯: each component actively uses the others, creating dependencies between them. This makes them difficult to scale and difficult to reuse.

Here’s another example using Redux state manager:

Architectures #3

In our setup, each component is managed by a designated “reducer” which handles its specific logic. However, some component logic was mistakenly placed in incorrect reducers. This might have happened because a developer was unaware of an existing file or didn’t consider creating a new one due to the limited amount of logic needed at the time. As a result, the logic for some components is now scattered across the project, making it less clear and harder to maintain.

we suggest reviewing the following diagram, which illustrates a missing architecture:

Architectures #4

This approach — (or perhaps more correctly, the lack of architecture 🥲) often causes a chaotic environment in which dependencies are difficult to track, leading to confusion and making it difficult to support the project. However, it may be useful for specific cases such as:

  • Small team (1–2 devs)
  • MVP project
  • Is not long term support project
  • Study project or templates

Modular architecture

Modular architecture — is an approach where the application is divided into layers (pages , modulescomponentsUI etc.) in which there are already independent modules with their own logic and area of responsibility.

Modular #1

In this example, you can see that the application layers are lined up in the same direction: pages→ modules→ components→ ui(or vice versa, if you look at it from the other side). This means that the higher the layer (e.g. pages), the fewer layers from the lower layer it can use - components can’t use modules, but can use everything from the UI layer, while modules use components but can’t use pages. And pages already only use modules.

Modular #2

As we have already mentioned, each module has its own area of responsibility. It is also important to say that each module should have its own public API (index.ts file), which encapsulates all the inner logic of the module and makes available only what is needed from the outside. (This is very similar to OOP principles: when a class has a lot of private methods that cannot be accessed from the outside, but can be used inside the class itself) When it comes to pages, it is quite simple: ideally it should be just an encapsulation of modules and components, and all the business logic of the application should be placed at the level of modules and components.

(⚠️) IMPORTANT: a module shouldn’t use another module, and a component should’t contain complex logic. If logic is still needed, it should be as simple and easily maintainable as possible, otherwise — it’s a module!

Take a look at the following diagram:

Modular 3

There is one “but …” — we still have global directories like components/ and ui/ that can be overused. In some cases, the logic can grow and it is no longer always clear what is a component and what is a module. In addition, it is often observed that as the application grows, developers start using modules within other modules, which breaks the principles of this architecture and causes unnecessary dependencies. However, our architecture provides:

  • Single-threading
  • Ability to reuse components at different layers
  • Almost perfect layering
  • Encapsulation

Feature Sliced Design (FSD) architecture

FSD #1

Feature Sliced Design (FSD) architecture — is a lot similar to modular architecture, but it also avoids the same “but…” we discussed above. This approach structures the project by functional areas (features) instead of just layers. This way of organizing helps to avoid global directory growth (like componentsUI in modular architecture) and provides a clear separation of responsibilities between components, modules and layers.

FSD #2

The architecture is built in such a way that the top level pages integrates and organizes the work of all submodules and components, and each next level provides more detailed and specific functions and elements. And yeah, we follow the same rule here — the higher the level (e.g. pages), the fewer layers from the lower level it can use:

  • Pages — The top level contains the pages that are displayed in the application.
  • Processes — deprecated in this architecture, so we can skip it.
  • Features/Widgets — Below the pages are the main features blocks that structure the core functionality of the page, making it managed and independent.
  • Entities — Below the feature modules are entities compiled from simpler UI components available in the “Shared” layer .
  • Shared — The bottom layer contains common UI components available for use in different parts of the application.

(⚠️) IMPORTANT: as in the case of modular architecture, the layers don’t overuse each other.

FSD #3

The FSD architecture features modular elements known as “slices” and “segments”. “Slices” refer to modules within each layer, each representing a distinct business entity. Meanwhile, “segments” encompass various structural components like api/components/config/constants/, and others, organizing the architecture into clearer, more manageable sections.

Finally, we’ve reached the target result:

FSD #4

This approach is not easy and fast to integrate into a project. It would require at least a minimum knowledge of architectures, and you have to keep in mind that it can take time. But mastering the use of FSD provides:

  • Clear Structure
  • Strong Defined Layering
  • Flexible Components
  • Independent Modules
  • Balanced Reusability

By the way, this architecture promotes “kebab case” in file naming 👀

product-description.vue / shopping-cart.tsx / get-base-url.ts / etc.


Examples of using “Modular architecture”:

Examples of using “FSD architecture”:

My other interesting articles:


Conclusion

In this article, we have explored the differences between classical, modular, and FSD architectures, and discussed their usages.

If this article has been interesting to you, read my next post, consider joining us live for our web developer conference Webstack in Bratislava, Slovakia where many other interesting themes are coming up, and not just about PHP and Laravel!

Webstack 2025

Let's Connect!

Have a project in mind or just want to say hello? Feel free to reach out—I’d love to hear from you!