Best Folder Structure for React Apps in 2023
First, take a look at Ternary Design System.
It goes like a tree shape that divides everything into 3 parts if possible, logical and necessary. So we have common
, test
and ui
folders in our root.
├── node_modules
└── src
├── index.js
├── __tests__
├── common (logic)
└── ui
The ./common
folder is for globally used services, constants, functions, states and other business logic modules and helpers.
├── common (logic)
├── navigation
├── store
├── constants
├── types
├── services
├── utilities
├── i18n
└── trackers
All of the UI-related instances are kept inside the ./ui
folder.
├── ui
├── pages
├── modules
├── assets
The pages
folder is comprehensible as its name stands clear. The modules
folder however is the key point of the Ternary Design System. It keeps partials
, blocks
and components
. Those are all globally consumed React components. We must first carry a modular approach and then elevate (bubble) them, if necessary.
So any part of our code might also possess the exact same structure. Here is an example component
:
└── components
├── HomeComponent
└── ExceptionallyLargeModal
├── __tests__
├── common (logic)
│ ├── atoms
│ ├── services
│ ├── functions
│ ├── constants
│ └── types
├── ui
│ ├── blocks
│ │ ├── Header.js
│ │ ├── Body.js
│ │ └── Footerjs
│ └── components
│ ├── GlobalInputProxy
│ ├── GlobalClickableFactory
│ └── LocalButton
├── ExceptionallyLargeModal.module.sass
├── index.js # exports ExceptionallyLargeModal.js
└── Loadable.js # Lazy loads ExceptionallyLargeModal.js
In the above-mentioned example, there is an ExceptionallyLargeModal
component that has an isolated, self-serving common
and ui
folders that store all the business logic and UI for the component itself. If we need any module somewhere else, then we elevate it relatively.
There is a crucial rule for the components that they MUST NOT contain any file directly inside, if not used for direct manipulation of the component instance (Example: “Home” component):
└── Home
├── index.js
├── Loadable.js
├── Home.js
├── Home.sass (or css)
├── Home.test.js
└── Slider.js (Wrong. It needs to be inside a "./components" folder)
This technique makes the code clean and readable, though it has a con that can cause overcomplication sometimes. You might end up with a folder hell.
└── ui
└── pages
└── Home
└── components
└── Slider
└── components
LeftButton
└── LeftButton.js
└── common
It is still clear to understand though.
The whole structure looks like this:
└── Ternary Design System example/
├── node_modules
└── src/
├── index.js
├── __tests__
├── common (logic)/
│ ├── navigation
│ ├── store
│ ├── constants
│ ├── types
│ ├── services
│ ├── utilities
│ ├── i18n
│ └── trackers
└── ui/
├── pages/
│ └── Home/
│ ├── index.js
│ ├── Home.js
│ ├── __tests__
│ ├── common (logic)/
│ │ ├── anyLocalServiceOfHome
│ │ └── constants
│ └── ui/
│ ├── partials/
│ │ └── HomePartialComponent
│ ├── blocks/
│ │ └── HomeBlockComponent
│ └── components/
│ ├── HomeComponent
│ └── ExceptionallyLargeModal/
│ ├── __tests__
│ ├── common (logic)/
│ │ ├── atoms
│ │ ├── services
│ │ ├── functions
│ │ ├── constants
│ │ └── types
│ ├── ui/
│ │ ├── blocks/
│ │ │ ├── Header.js
│ │ │ ├── Body.js
│ │ │ └── Footerjs
│ │ └── components/
│ │ ├── GlobalInputProxy
│ │ ├── GlobalClickableFactory
│ │ └── LocalButton
│ ├── ExceptionallyLargeModal.module.sass
│ ├── index.js # exports ExceptionallyLargeModal.js
│ └── Loadable.js # Lazy loads ExceptionallyLargeModal.js
├── modules/
│ ├── partials/
│ │ └── GlobalPartialComponent
│ ├── blocks/
│ │ └── GlobalBlockComponent
│ └── components/
│ └── GlobalComponent
└── assets/
├── fonts
├── styles/
│ └── theme.js
├── images
└── colors