WORK STORY / 03
Turn folder structure into executable rules
Context
As the number of repositories, Shared Packages, and products grew, I encountered another problem.
Even when everyone knew:
- Where a component should live
- Which layer should own business logic
- What contexts, hooks, and services should each own
Implementations by different engineers could still easily produce different dependency directions.
Over time, folder structure became only:
“the files look neatly organized”
while the actual dependencies had already penetrated one another.
A component directly accessing a service, a lower-level module depending back on an upper layer, or even a type definition assigned to the wrong owner could gradually create circular dependencies.
My Decision & Action
I therefore began developing folder structure from a directory-naming convention into an architectural rule.
I redefined the responsibilities of each layer, including:
- pages
- containers
- components
- hooks
- contexts
- services
- utils
and further defined the import directions allowed between them.
For example, components should not access services directly; contexts, hooks, and containers may obtain capabilities only from specific layers; and TypeScript types must have clear owners rather than being referenced everywhere for convenience.
Besides documenting these relationships with text and dependency diagrams, I gradually constrained imports through ESLint rules so architectural rules were not merely instructions written for people.
Outcome
Folder structure no longer asked only:
“Which folder should this file go in?”
It began to answer:
“What should this layer know, and what should it not know?”
The team could use one structure to understand module responsibilities and detect unreasonable cross-layer dependencies early in development.
Reflection
This is also a principle I have continued to follow:
If an engineering rule truly matters, it should not exist only in documentation.
Documentation is suited to explaining why, but anything tooling can judge should preferably be judged directly by tooling.
Otherwise, standards ultimately become shared conventions engineers must uphold through memory.