Folder structure

The context

According to our first principle, the codebase should primarily reflect the business domain. Frameworks and libraries are secondary considerations - implementation details.
Folders and files are organized first around the entities that are manipulated. Proper names convey the purpose of the application: what can I do with it?
One common problem is to structure code according to a framework or library's requirements. It is almost always a mistake. Such solutions mask the real purpose of the module or application, while also couple the whole codebase to a specific technology.
Another mistake is to organize source files by type, for example, to have a dedicated folder for all images, another for CSS, components, resolvers, etc.
Every module should reflect the entities it works with as top-level folders - this is the work context. When there is a hierarchy, we use subfolders. When there is no more domain-driven context to talk of, a technology-driven grouping can happen.
The above also means that context-free group names like "utils" or "helpers" are pointless and are strongly discouraged. They are not domain-driven, not technology-driven and don't convey meaning. There is always a better name than these.
Another consequence of context-driven grouping is that the test, mock and all supporting files live next to the source files (co-location). Co-locating makes clear if there is a test for a module and avoids creating a shadow folder-tree.
More importantly, all resources are at hand when working in a specific context. The developer can see the source, the tests and any relevant assets. There is no need to open files from multiple, far-away directories, and there is no guessing. It is obvious where to implement changes.
A regular question is where to store UI components that are shared across all domain types, for example, buttons, typography. Since these don't have a domain context, they can live in a group named base, baseComponents. components has the danger of luring every component in, even context-specific ones, so it's not the best choice.

Index files

Do not add index files to folders. This practice has several drawbacks:
    It needs to be done manually, which is a drain on attention and energy (no matter how small it appears)
    It's just another thing to remember
    Makes refactoring harder, as you'll need to edit the re-exports
    Makes moving modules around harder
    It seems like a cosmetic change
    It is a code smell
Making refactoring harder usually means it never happens, which is far from ideal.
In any case, when using correct grouping, the full path to a module is usually pretty short.
The only exception to this rule is when creating a local or public npm package: the module's top-level exports are best exposed using an index file so clients can import without mentioning a path (which is an implementation detail to be hidden). For this reason, our domain, service etc. modules will have a top-level index file, but only one and it is used only from the outside.

Example

Here is an example for confusing and a clear grouping of source files:
1
# Do not do this
2
src/
3
__tests__
4
date.test.ts
5
components/
6
index.ts
7
LaptopList.tsx
8
css/
9
Laptop.css
10
images/
11
keyboard.png
12
utils/
13
sortMarbles.ts
14
date.ts
Copied!
A good example
1
src/
2
laptop/
3
LaptopList.tsx
4
Laptop.css
5
keyboard.png
6
date/
7
date.test.ts
8
dateFormat.ts # Maybe this is a domain module?
9
sortMarbles.ts # "1 or more"
Copied!
Hint: you can use the "1 or more" rule to decide if something needs to go into a subfolder. If there is only one "thing", the file can live where it is (e.g. sortMarbles.ts above). If there is two or more, put them in a subfolder (e.g. marble/sortMarbles.ts)
Last modified 1yr ago