Frontend Architecture Patterns Explained in 10 Minutes
Frontend architecture is a very overlooked topic. Not many of us take it seriously when we are working on projects. But here's the thing: frontend apps have become complex enough that we really need to consider their architecture as a crucial part of the development process. In this article, we will look at some popular frontend patterns, discuss their advantages, and talk about when we should use them and when we shouldn't. Let's dive in.
What is Software Architecture?
When developers hear the word "architecture," a lot of them immediately think about files and directories. And while that's part of it, it's not the main idea. Architecture isn't just about how your files are structured; it's about how different layers of your app interact with each other.
You might have heard of MVC, or Model-View-Controller, which was a pretty common pattern back in the day. Even though it's not as widely used now, especially in modern frontend apps, the concept still helps us understand how different parts of an application communicate. Your architecture can dictate how your files are structured, but it doesn't have to. For example, if you put every single file into one folder (which of course nobody on your team will like), you'll still have an architecture as long as your components interact in a structured way.
Why Do We Need Architecture?
- Flexibility: It allows different parts of the app to be modified or replaced without affecting everything else. Realistically, how often do you replace React with Vue? Probably not too often. But flexibility isn't just about swapping frameworks; it's about having clear boundaries between components to make maintenance easier.
- Testability: Individual layers are easier to test.
- Scalability: As an app grows, a clear separation of concerns helps manage complexity.
The importance of architecture depends on three key factors:
- Project Size: Bigger apps require more structure to stay maintainable.
- Team Size: The more people working on the project, the more critical architecture becomes. Even if you're just a two or three-person team, having some architecture is still beneficial. But in a team of 10 to 15 developers, good architecture is a must.
- Project Lifetime: For a short-lived MVP, we can prioritize speed over structure, but long-term projects need solid architecture to prevent technical debt.
One thing to note: architecture often slows down initial development, but in the long run, it makes scaling and feature development much faster.
MVC: Model-View-Controller
Most of you have probably heard of it. It's been around for over 36 years. And while it's not commonly used in modern frontend applications, it still contains some fundamental concepts and can be useful in its own right to help us understand more complex patterns.
MVC breaks an app into three main layers:
- Model: Represents the application data and business logic. This layer is usually represented by the backend, database, and sometimes an API.
- View: Responsible for displaying data. This is the UI—what the user actually sees on the screen. It can also include UI logic, like opening a modal window.
- Controller: Acts as a bridge between the Model and View. It handles user input, updates the model, and tells the view what to display.
MVC Workflow in 5 Steps
- User Input: This is where everything starts. The user clicks a button, types something, scrolls, swipes—basically any kind of interaction.
- View Captures Input: The View captures the input and passes it to the Controller. At this stage, the view itself doesn't process the event; it just forwards it.
- Controller Processes Input: The Controller takes the input and decides what to do with it. If the action requires updating the database, the controller sends a request to the Model. For example, if the user clicks "delete item," the controller tells the model to remove it from the database.
- Model Updates Data: The Model, which is usually the backend or a state management system, processes the request and modifies the data accordingly.
- View Updates: Here's where things get interesting. Both the Controller and Model can update the View. The question is, how does the model communicate changes to the view? There are two common approaches: the Observer Pattern, where the view subscribes to updates from the model and reacts automatically, and Flow Synchronization, where the view explicitly asks the model for updates when needed.
Finally, the changes are reflected in the UI, and the user sees the updated state of the app.
Thin vs. Thick Clients
This distinction defines how much processing happens on the client-side versus the server-side.
- Thin Client: Keeps most of the processing on the server, while the client web app only handles the UI and user interactions. This is common in traditional multi-page applications. Every interaction goes to the server, which does all the processing and sends back an updated page.
- Thick Client (Fat Client): Performs a lot of logic on the client-side, reducing the server workload. Most interactions are handled instantly on the client-side, sometimes even offline.
A thin client is heavily dependent on the server, whereas a thick client can work more independently. SPAs, Progressive Web Apps, and local-first applications rely on thick clients to improve user experience, but this shifts more complexity to the frontend.
MVP: Model-View-Presenter
MVP evolved from MVC to better fit modern web applications. In MVP, the view doesn't communicate with the model directly. Instead, everything goes through the Presenter. Remember how in MVC, we had to put observer logic into the view? MVP solves that by moving this logic into the presenter. So now the view is just a pure UI layer, nothing more.
This makes the system: * More predictable: No weird circular dependencies. * Easier to test: The view contains no logic. * More structured: Each layer has a clear role.
There are two types of MVP: 1. Supervising Controller: The view still handles some simple updates on its own; only complex logic goes through the presenter. This is faster for development but makes the view harder to test. 2. Passive View: The view is completely passive; all logic is handled by the presenter. This creates clearer boundaries and is easier to test but requires more boilerplate code.
MVVM: Model-View-ViewModel
The main idea of MVVM is to separate view logic from business logic.
- Business Logic: When we actually modify data in some way (e.g., changing a username, making a payment).
- View Logic: Purely UI-related stuff that doesn't modify real data (e.g., opening a modal, disabling a button).
Modern web applications like Figma or Google Calendar are insanely complex, with tons of UI updates. If we throw all this UI logic into the view layer, things get messy fast. That's where MVVM comes in.
MVVM has three parts: * View: The UI, same as always. * ViewModel: Handles all UI-related logic. * Model: Handles business logic and actual data.
The key difference is the ViewModel, which takes care of all UI logic and ensures the UI stays in sync with the data. MVVM introduces a concept called two-way data binding. This means that when you change something in the ViewModel, the View updates accordingly, and when you change the View (e.g., user input), the ViewModel updates automatically.
Hierarchical MVC (HMVC)
MVC works great for small applications, but once your app grows, it starts to fall apart. This is where HMVC comes in. Hierarchical Model-View-Controller is an extension of MVC that fixes its scalability issues. Instead of one big MVC structure controlling everything, we break it down into smaller, independent MVC blocks. Each block handles a specific feature and interacts with other blocks only through its controller.
This decoupling makes the architecture more modular, reusable, and scalable. If you've worked with Angular, this concept should sound familiar; its feature modules are an implementation of HMVC.
MVVMC: Model-View-ViewModel-Coordinator
If you've already learned about MVVM, then you already know most of this. The only new thing here is the Coordinator, and its job is to manage navigation and screen transitions.
In MVVM, there's no clear place to handle navigation. The View is just UI, the Model is just data, and putting navigation logic in the ViewModel makes it bloated. The Coordinator solves this by moving all navigation logic into a separate entity.
VIPER: View-Interactor-Presenter-Entity-Router
This pattern offers even more structure. * View: A passive view that just displays UI and forwards user actions. * Presenter: Prepares data for the View. * Interactor: Handles business logic (fetching/modifying data). * Entity: Raw data, no logic. * Router: Manages screen transitions and navigation.
In VIPER, we split the logic into even more layers to keep things modular and scalable. It's used mostly in mobile development but can be applied to web apps. It adds more structure than classic MV patterns, making it better for large-scale applications.
Clean Architecture
Introduced by "Uncle Bob" Martin, this approach has four main layers: 1. Entities: The core business logic. 2. Use Cases: The application logic. 3. Interface Adapters: A bridge between use cases and external systems. 4. Frameworks & Drivers: Things like databases, UI frameworks, and APIs.
The key principle is the Dependency Rule: dependencies always point inward. The inner layers don't know about the outer layers. This makes the architecture highly testable, modular, and independent of frameworks, UI, and databases.
Hexagonal Architecture (Ports & Adapters)
This pattern focuses on a central piece of business logic with ports that allow external systems to connect. These external systems use adapters to interact with the ports.
Imagine two teams: a backend team builds the business logic and defines the ports. A frontend team builds a UI adapter that connects to those ports. The UI team doesn't need to know how the backend works internally. This facilitates distributed development and is great for systems with multiple interfaces (e.g., REST API, GraphQL, CLI).
Screaming Architecture
This concept, also from Robert Martin, is about how we structure our code. The idea is that the architecture of a software system should be immediately recognizable just by looking at its top-level structure. The architecture should "scream" the intent of the application.
Instead of organizing your project by technical layers (/controllers
, /views
), you should organize it by business features (/users
, /orders
). This makes it obvious what the system does without digging into the details.
Vertical Slices Architecture
This is one of the most modern and widely used architectural styles today. It complements layered architectures like Clean Architecture. Instead of separating the application into horizontal technical layers, you slice it vertically by feature.
Each "slice" is a self-contained feature that includes its own entity, use case, controller, and interface. This makes the architecture more modular, easier to scale, and more maintainable. It's particularly beneficial for large-scale applications where multiple cross-functional teams can own features from end to end.
Final Thoughts
While we've explored several patterns, we certainly didn't cover all of them. The goal was to focus on the most widely used ones. It's also valuable to borrow ideas from other fields, like mobile and backend development.
The topic of frontend architecture has been overshadowed for a long time, but modern frontend applications have become extremely complex. They manage state, caching, data persistence, and synchronization. That's why frontend architecture should be more widely discussed.
Finally, remember that patterns are not meant to be followed rigidly. Every project is unique, so you must adapt these patterns to fit your specific needs. Their greatest advantage is providing a common language for developers to communicate effectively about the structure of an application.
Join the 10xdev Community
Subscribe and get 8+ free PDFs that contain detailed roadmaps with recommended learning periods for each programming language or field, along with links to free resources such as books, YouTube tutorials, and courses with certificates.