Skip to content

React JS Folder Structure

Spinning Idea edited this page Aug 3, 2022 · 20 revisions

React JS Application Folder structure

There are a number of approaches to structuring the folders within a React JS application. Below is one approach that allows clear convention and organization.

Architecture

Top Level Folders

Below is the main folder structure under the "src" folder. This is the "source" code that is built and packaged into the deployed application

src
├── assets
├── components
├── config
├── contexts
├── hooks
├── layouts
├── routing
├── stores (or services)
├── styling
├── tests
└── utilities

Routing

One of the starting points in the application is the router which controls the loading of pages and overall application flow from user/client perspective. This folder encapsulates the router and references to pages and rules around route parameters that are passed into pages as key data points that a given page needs.

See: https://github.com/remix-run/react-router

Example

Keep a consistent name between the page and the route:

<Routes>
  <Route path="/" element={<Home />} />
  <Route path="about" element={<About />} />
  <Route path="sign-in" element={<SignIn />} />
</Routes>

Pages

Pages are the top level components that are referenced in the router and user requests are routed to by the main router. They are components themselves that leverage other components to compose the page and work surface as a whole. Pages form the primary building block of an application and differently from the other components, are very strictly scoped (and own specific URL path similar to an API controller owning a route segment). Instead of having a single page application this approach breaks apart the application into an "MPA" or Many Page Application.

Example

pages
├── home.tsx
├── about.tsx
├── signin.tsx

For the home and about it's fairly simple, a page is supposed to be the result of the composition of other components, which have proper tests, so create a specific directory for them under the tests folder in the pages directory.

The case is different for the sign in page, which has something specific, a sign-form component put any child components such as the sign in form in the "main" component folder in a subfolder with the name of the page (sign-in). If the application grows, and the signin-form component will be used in several pages, nothing prevents you from moving it to "common" folder.

This approach is powerful because lets you split the code into small chunks, but keeps the architecture well organized and the convention if followed allows reasoning about where to put a component and where one should find it.

Components

Components folder contains all the components that are used more than one single time in the app including every feature-specific component.

Create subfolders to differentiate between application, page, and common or shared reusable logic. A button is supposed to be used on almost every page of our app, so that goes into "common" directory. The signup-form component is page specific so that goes into a subfolder with that page name.

Suppose you have two different pages for sign-in and sign-up, this component needs to be repeated two times, that’s the reason why is put into the components folder but as a scoped into subfolders by page name within components.

Examples

common

├── components
│   ├── common
│   │   └── button
│   │       ├── button.tsx
│   │       ├── button.stories.tsx
│   └── signup
│       ├── signup-form.tsx
│   └── home
│   │   ├── getstarted.tsx

Some examples of what can be inserted into the common folder:

Notice also that every single component is placed into a proper directory and follow the naming convention.

button
├── button.tsx
├── button.stories.tsx
└── index.ts

The application can eventually contain many dozens of components so having a consistent structure is important to avoid confusion and for others to easily find and know where to put new work.

Some key points of this folder:

  • All the component-related files are in this folder.
  • All the exportable modules are put into an index.ts to avoid double name in import.
  • All the files are named in kebab-case.

Questions

  • Where is the button component? -> In the button folder.
  • Where are the stories for this button? -> In the button folder.
  • Where are the tests for this button? -> In the tests folder under components/button folder.

Layouts

Layouts are not pages but rather they are components that layout the application page structure to include menuing and header, footer. If need arises for different layouts you can put them all in this folder.

Example

layout
├── main.tsx
└── auth.tsx

One thing you may notice is the name is not main-layout.tsx but just main, that's because following this reason you would have to rename all the components like table-component.tsx which is weird. Name all the components without the obvious suffix given by the parent directory, and if one needs to underline that an import alias "MainLayout" can used to clarify things within the context of the application shell.

import { Main as MainLayout } from "@/layouts/main.tsx";

Contexts, Hooks & Stores

Use kebab-case lower case for all the filenames:

Examples

hooks
├── use-auth.ts
└── use-click-outside.ts
contexts
└── authentication.tsx
hooks
├── use-users
│   ├── use-users.ts
└── use-click-outside.ts

Utilities

Often the application and pages or components need shared functions for handling currency or dates or processing collections in javascript (eg formatCurrency function that properly formats and adds a dollar sign - put currency formatting in currency.ts and any date formatting in date.ts)

The utilities folder is the place to put these library functions.

Example

utilities
├── currency.ts
├── dates.ts
└── collections.ts

Also, put constants in a single file to encapsulate them into a specific file.

// @/constants/index.ts
export const SUPPORT_EMAILADDRESS = "support@email.com";
export const SUPPORT_USERNAME = "Support";

// And use them
import { SUPPORT_EMAILADDRESS , SUPPORT_USERNAME } from "@/constants";

Services (or Stores...)

The services folder holds the capabilities to make outbound calls to APIs to get and set data and can include authorization and other things like localization. The subject of using stores or services to manage state and external API communication is a complicated one.

See More: https://github.com/spinningideas/resources/wiki/React-JS-State-Management

Styling (CSS, Fonts, Colors)

Put global styles into a "styling" folder. You can put theming here as well. This folder is meant to encapsulate all the things that involve the CSS and styling of the application including font faces and any third-party libraries.

See UI Kits: https://github.com/spinningideas/resources/wiki/React-UI-Toolkits

Example

Application

styles
├── index.css
├── colors.css
└── typography.css

Components

What about CSS for individual components?

button
├── button.tsx
├── button.stories.tsx
├── button.styled.tsx
├── button.module.scss
└── index.ts

If you are using emotion, styled-components, or simply the CSS Modules, put them into the specific component folder, so everything will be optimally packaged.

Tests

In order to separate out tests but create an area for them that follows the larger convention of using pages and components folder and placing that structure containing the tests for these under the "tests" folder so they are centrally located and managed.

Example

tests
├── components
│   ├── common
│   │   ├── button.spec.tsx
│   └── signup
│   │   ├── signup-form.spec.tsx
│   └── home
│   │   ├── getstarted.spec.tsx
├── pages
│   ├── home.spec.tsx
│   ├── signup.spec.tsx

Asset Files

The "assets" folder avoids root directory and contains the physical assets such as images, fonts or data like json files (geography data in example below).

Example

assets
├── images
│   ├── logo.png
├── fonts
│   ├── noto-sans.woff
│   ├── noto-sans.ttf
├── data
│   ├── countries.json
│   ├── states.json

Config Files

The config folder avoids root directory pollution with non-relevant files. The config folder should contain Application configuration files like Dockerfiles, Fargate Task Definitions, and so on.

See Also

Clone this wiki locally