Best Folder Structure for React Apps in 2023

Babek Naghiyev
3 min readNov 12, 2022

--

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, testand 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.

Partials -> Blocks -> Components

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 uifolders 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

--

--