Other architectures: pros and cons
By type, feature-based, Atomic Design, Clean/Hexagonal and monorepos.
Updated
What you're comparing
There's no "best" architecture — there's the one that fits the project's size, the team and how complex the domain is. Below are the most used options in the frontend, with pros, cons and when to choose them.
1. By file type
src/components/ src/hooks/ src/utils/ src/services/ src/types/
+ zero learning curve, perfect for small projects / prototypes. − at 100+ files it becomes a "junk drawer"; a feature is scattered across 5 folders; no dependency rules.
When: a landing page, a personal project, < ~30 components.
2. By feature / module (Bulletproof React)
src/features/
auth/ components/ api/ hooks/ types/
cart/ components/ api/ hooks/ types/
src/components/ (shared)
+ high cohesion, easy to understand, scales well; a simple rule: features don't import each other. − fewer rules than FSD → "where do I put code used by 2 features?" is left up to the team.
When: most medium-sized apps. It's the most popular alternative to FSD.
3. Atomic Design
atoms/ (Button, Input) → molecules/ (SearchField) → organisms/ (Header) → templates/ → pages/
+ excellent for a design system / UI kit; a shared vocabulary with designers. − organizes only the UI, not the logic or the data; the molecule/organism boundary is subjective.
When: component libraries, Storybook. It can live inside shared/ui of another architecture.
4. Clean / Hexagonal (Ports & Adapters)
domain/ entities + pure rules, no framework
application/ use cases (createOrder)
infrastructure/ DB, API, concrete implementations
ui/ React
+ the business logic is completely independent of the framework → testable, portable. − lots of boilerplate (interfaces, adapters); in the frontend it's often over-engineering.
When: a complex domain (fintech, ERP), logic shared between web/mobile/backend.
5. Monorepo (Turborepo / Nx)
apps/web apps/admin apps/mobile
packages/ui packages/config packages/db
It's not an alternative, it's a level above: several apps that share packages. Each app picks its own internal architecture (often: FSD or feature-based).
+ real shared code, cached builds. − tooling complexity.
A quick comparison
| Project size | Rules | Learning curve | Business logic | |
|---|---|---|---|---|
| By type | small | few | easy | scattered |
| Feature-based | medium–large | medium | easy | per feature |
| FSD | medium–large | strict | medium | entities/features |
| Atomic | UI kit | UI only | easy | — |
| Clean/Hexagonal | large, complex | strict | hard | an isolated domain |
How to choose
- A small project or a prototype → by type, move later.
- A product app, a small team → feature-based.
- An app that will grow, several devs, you want tooling-enforced rules → FSD.
- A design system → atomic inside
shared/ui. - A very complex domain → ideas from clean architecture (pure logic kept separate), not necessarily the whole ritual.
The worst architecture is one applied inconsistently. Pick one, write the rules in the README and enforce them with lint.
Summary
- By type for small projects; feature-based for most apps; FSD when you want strict rules.
- Atomic Design for a UI kit; Clean Architecture for complex domains; a monorepo for several apps.
- Pick one, document it, enforce it with lint.