The Frontend Is an Application: Stop Treating It Like a Template
A frontend codebase is not a thin layer over a backend. It's a full application with its own state, domain, and architecture. Here's how I argue for treating it that way — and the patterns that follow.
Every senior frontend engineer I respect has the same scar: the moment they realized the codebase was being treated as decoration rather than as software.
Symptoms look like this. Components fetch data inline. Business rules live next to JSX. “Just render what the API gives you” is repeated as if it were architecture. Tests are slow and flaky because every assertion mounts a tree. The build gets bigger every quarter and nobody can explain why.
The reframing
A frontend is not a view of a backend. It is a separate application with:
- Its own domain model — the types and rules that govern what the UI is allowed to do.
- Its own use cases — actions the user can take, expressed without mentioning HTTP.
- Its own boundaries — repositories that adapt the network into domain entities, not raw payloads bleeding into components.
export class GetProfile { constructor(private readonly profiles: ProfileRepository) {}
async execute(): Promise<Profile> { return this.profiles.getOne(); }}The component that calls getProfile.execute() doesn’t know if the data came from REST, GraphQL, IndexedDB, or a mock. That ignorance is a feature.
What changes when you take it seriously
- Tests get fast. The domain runs without a DOM. Most assertions complete in single-digit milliseconds.
- Onboarding gets short. A new engineer can read
domain/and understand the product before touching a single component. - Refactors get cheap. Swapping a fetch library, a state manager, or even a framework stops being a rewrite.
A frontend codebase deserves the same architectural rigor as any other application. The fact that it ships pixels is an implementation detail.