August 5 2025
How to Modularize a Frontend for Real
Good modularization reduces blast radius and improves understanding. When it turns into folder theater, it only increases navigation cost.
Andrews Ribeiro
Founder & Engineer
4 min Intermediate Frontend
The problem
When a frontend grows, the urge to “modularize everything” shows up.
That can help a lot.
But it can also produce a cosmetic renovation:
- more folders
- more
index.ts - more re-exports
- more sophisticated names
and almost no real improvement in how the codebase evolves.
If the change does not reduce:
- blast radius
- cross-imports
- reading cost
- fear of touching the code
then it probably still is not real modularization.
Mental model
A good module creates a change boundary.
That means:
- people changing the inside do not need to understand everything outside
- people using it from the outside do not need to know its internal details
- dependencies enter through more predictable points
Short version:
modularizing is not splitting the frontend into more pieces. It is making each piece depend on less context so it can stay healthy.
What good modularization usually gives you
1. More local reading
Someone opens a flow and can understand:
- where it starts
- what composes the screen
- where the main logic lives
- what is internal detail
Without architectural tourism across twenty random files.
2. A smaller public surface
A good module exposes little and hides a lot.
If everything can be imported from anywhere, the boundary is weak.
3. A smaller radius of change
When you change something inside a module, the goal is not to trigger side effects across too many areas.
If any adjustment forces you to touch half the application, the structure still is not helping.
Signs of architectural theater
Some smells show up quickly:
- deep folders with little real criteria
- barrels at every level
- generic names like
core,common,base,utils - one feature importing internal details from another feature
- sophisticated structure with the same dependency mess underneath
That creates the feeling of architecture, but not real safety.
Simple example
Imagine an admin frontend.
The theatrical version:
modules/shared/core/common/presentation/domain/infra/
Everything exists.
But:
- billing components import onboarding utilities
- a search hook depends on a global store with no boundary
- API details leak into screens
The more honest version:
- each important area has its own folder
- there is a clear entry point
- details stay more local
- shared stays small and strict
- cross-imports are the exception, not the rule
It may look less “architected” in a screenshot of the tree.
But it is usually more sustainable.
A practical way to start
If the codebase is already large, better modularization rarely starts with a heroic migration.
It usually works better like this:
- choose an important and painful flow
- identify what is actually the public entry point of that slice
- reduce direct imports into internal details
- group together what changes together
- leave the rest for later
That is how real modules tend to appear little by little.
The role of dependency discipline
A lot of modularization fails because the tree changes but dependency rules stay loose.
If any file can import any other file:
- shared grows the wrong way
- modules lose their boundary
- refactors become risky
Even without a formal tool, it already helps a lot to make agreements explicit, like:
- one feature does not import internal details from another feature
- the design system does not know domain logic
- shared does not become a dump for everything left over
How a senior thinks
People who have suffered through large frontend codebases usually judge modularization by real effect:
- did it become easier to change?
- did reviews become more local?
- did imports become more predictable?
- does the team understand better where each thing belongs?
That bar is much better than any purely aesthetic argument about the directory tree.
Interview angle
This topic shows up in:
- frontend system design
- questions about scaling a React codebase
- discussions about legacy and refactoring
Weak answer:
I would organize the frontend by modules.
Strong answer:
- explains which boundary should be protected
- shows how to reduce coupling
- talks about public surface, dependency, and blast radius
That shows you are not confusing folders with architecture.
Closing thought
Modularizing a frontend is worth it when the system becomes more predictable both for the people building it and the people maintaining it.
If the new structure only produces more layers, more names, and more re-exports, it may be serving architectural ego more than the product.
Good modularization does not make the tree look sophisticated. It makes change feel less dangerous.
Quick summary
What to keep in your head
- Good modularization reduces blast radius and the cost of understanding, not just the number of files.
- If the new structure still allows cross-imports in every direction, it organized names, not dependencies.
- Moving code into modules helps more when there is a clear public surface and hidden internal detail.
- In large frontends, modularizing is usually a progressive process, not a theatrical folder migration in one giant PR.
Practice checklist
Use this when you answer
- Does this module have a real boundary, or did it only get its own folder?
- Does someone changing this feature need to open half the codebase, or can they reason locally?
- Are there clear entry points, or can any file import any other?
- Am I reducing coupling or only renaming chaos?
You finished this article
Share this page
Copy the link manually from the field below.