Client-side Architecture
Most frontend codebases do not start messy; they grow messy. The first version is a few files that do exactly what is needed, and then features pile on, a fetch call sneaks into a view, a component starts holding business rules, and a year later nobody can change one screen without breaking another. Client-side architecture is the set of decisions that keep that from happening, by deciding up front what each part of the app is allowed to know and do.
This guide takes the layered picture from SPA architecture and turns it into practical structure. It deepens the application-structure and data-flow ideas from Foundations.
What you'll learn
Why client-side structure matters
Structure is not bureaucracy; it is what lets a codebase keep changing cheaply. The cost of a change should depend on the size of the change, not the age of the project, and only a deliberate structure keeps that true.
From a script to a system
A small app can be a single script, and that is fine until it is not. The moment several people, several features, and several months are involved, the absence of structure shows up as fear of touching anything. Investing in layers and boundaries early is what turns a pile of scripts into a system you can reason about one piece at a time.
Separation of concerns
The core idea underneath all client-side architecture is old and simple: each part of the program should do one kind of thing. Rendering is one concern, deciding what happens is another, and managing data is a third.
One responsibility per layer
When concerns are separated, a change to how something looks does not risk how it behaves, and a change to a data source does not ripple into the UI. When they are tangled, every edit is a guess about side effects. Almost every rule that follows is just a specific application of this one principle, give each layer a single, clear responsibility.
The common layers
Frontends of all kinds tend to converge on the same few layers, whatever framework draws them. Naming them makes the structure explicit instead of accidental.
View, logic, and data layers
The view or presentation layer renders the interface and captures input. The application-logic layer coordinates what the app does in response, the rules and workflows. The data or domain layer handles fetching, caching, and the shape of the data, the concern isolated in the data-flow guide. Bigger apps add a services layer for cross-cutting needs like authentication or logging. Whatever the names, the point is that each layer owns one slice of the problem.
Dependency direction
Layers alone are not enough; what keeps them honest is which way the dependencies point. A clean architecture lets higher layers depend on lower ones, and never the reverse.
Keeping dependencies pointing one way
The view may depend on the logic and data layers, but the data layer must not import the view, and logic should not reach up into specific components. When dependencies point one way, you can change or replace the view without disturbing the logic beneath it, and test the lower layers without a UI at all. A dependency that points the wrong way is the usual seed of tight coupling, so it is worth catching early.
Keeping views thin
With the layers and their direction set, the single highest-leverage habit is keeping views thin. A thin view knows how to display state and how to announce that something happened, and nothing more.
Logic out of the view
// View: render and emit, no business rules
function CartView(state, emit) {
return button({ onClick: function () { emit('checkout'); } }, 'Checkout');
}
// Logic layer decides what 'checkout' actually does
function onCheckout(store, services) {
// validate, call the API, update state
}
The view emits a checkout event; the logic layer decides what that means. Pushing rules out of components this way keeps them small and swappable, makes the logic testable without rendering anything, and stops the same rule from being copied into three different screens. When a view starts making decisions, that is the signal to move the decision down a layer.
Module boundaries and feature folders
Layers describe horizontal slices, but a large app also needs vertical ones, organized around what the features actually are. This is where folder structure stops being cosmetic.
Organizing by feature
Grouping code by feature or domain, a cart, a profile, a checkout, each with its own views, logic, and data, keeps related code together and unrelated code apart. Expose a small, clear interface from each module and keep its internals private, so features can evolve without reaching into each other. Combined with the layer rules, organizing by feature is what lets a big frontend grow without every part becoming entangled with every other. The next guides zoom into individual layers, beginning with the routing layer that decides which view the user sees.
Frequently Asked Questions
What is client-side architecture?
Client-side architecture is the way you structure a browser application into layers and modules, typically presentation, logic, and data, so that it stays understandable and maintainable as it grows. It is about boundaries and responsibilities, not any specific framework.
What are the layers of a frontend application?
Most frontends settle into a view or presentation layer that renders the UI, an application-logic layer that coordinates behaviour, and a data or domain layer that handles fetching and state. Larger apps may add a services layer for cross-cutting concerns. Each layer has a single responsibility.
Where should business logic live in a frontend app?
Business logic belongs in an application-logic or domain layer, not inside view components. Views should render the current state and emit events, while the logic layer decides what those events mean, which keeps the logic reusable and testable.
How do I keep a large frontend codebase maintainable?
Separate concerns into layers, keep dependencies pointing one way so lower layers do not import the view, keep views thin, and organize modules by feature with clear interfaces. These habits stop a growing app from collapsing into tightly coupled code.
Read next: back to the Frontend Architecture hub, or revisit SPA architecture for the layers in context.
Want to see these layers wired up?
The complete Backbone guide builds views, logic, and data as separate pieces you can follow.
Explore the Backbone Guide →