Back to Blog
architecturereactvueengineering-culture

What I've Stopped Calling 'Frontend Architecture'

March 22, 20264 min read

What I've Stopped Calling "Frontend Architecture"

I used to love the word. I'd argue about it in PR reviews, put it on slide decks, talk for half an hour at a whiteboard about whether something belonged in features or domain or entities. I no longer trust most of what I used to say.

It's not that frontend architecture doesn't exist. It's that the word has become shorthand for whatever the speaker wanted to do anyway. Somebody wants a monorepo because they read about Turborepo: architecture. Somebody wants features/ instead of pages/: architecture. None are wrong, exactly — they're folder structure and build configuration, dressed up in a word that implies more rigor than they contain.

The four mistakes I championed in 2022

Around 2021–2022 I put a lot of state into Redux — form state, modal open/closed, hover state on list items. The reasoning was that "one place to look for state" was good. This was wrong. Transient UI state in a global store couples components that have no business knowing about each other, and turns the Redux inspector into a firehose. Server data, auth, theme — yes. Hover state — no.

I also led a project that split a working app into four Nx packages because one might be reused someday. The other app never got built. We spent a year paying the tax — package boundaries, circular dependency errors, build orchestration breaking every time someone updated a dep. Monorepos make sense when you already have two real consumers. Not before.

I partly designed a codebase where every API call went through a use case that called a repository that called an adapter that called fetch. Beautiful on the whiteboard. Adding an endpoint touched five files and only one person fully understood the layering. Six months after I left, someone simplified it down to thin API clients.

The one I'm most embarrassed about is the <Form> wrapper. We had two forms. I built one component that handled validation, errors, submission, optimistic updates, and a half-dozen edge cases. The third form didn't fit. We extended the abstraction. The extension broke the original two. By the time we had four forms, the wrapper was 500 lines with an eighteen-option config object. We ripped it out and wrote each form as its own small thing.

The pattern in all four is the same: I optimized for an imagined future that didn't arrive and paid the cost in real present-day complexity. Premature generalization is the most expensive thing I've consistently done as a frontend engineer, and the insidious part is that it always looks, in the moment, like the senior thing to do.

The actual architecture problem is shared state

Almost everything else in a frontend codebase can be reorganized later. Shared state can't, easily. This is where the word "architecture" still earns its keep.

The good codebases I've worked in handle this with careful prejudice. Things genuinely shared — current user, theme, active workspace — live in dedicated stores. Things coincidentally shared — two components that both happen to need the current row's data — are passed explicitly, not promoted to global. The bad codebases treat the distinction as style, and pay for it for years.

What I do now

I judge codebases by one question: can a new contributor figure out where to add a feature without DM-ing anyone? If yes, the team has legibility. If no, no number of conference-approved patterns will fix it. Folder structure barely matters. Consistent conventions do.

The people I respect most hold their architectural preferences loosely. They refactor toward problems rather than ideals, and they're comfortable saying "I don't know, let's start simple and see what hurts." That phrase is doing more work in a healthy codebase than any architecture document ever does.