Intro
I've been working with React for over 4 years. During this time, I've formed some opinions on how I think applications should be. This is part 1 in a collection of those opinions.
Folder Structure & File Naming
I have gone through many iterations of folder structure in the applications that I worked on. The one that I have found scales the best is to have flat folders and long file names. Since I use VSCode, it is easy to search for files, so the longer the name, the better. Here's how I layout most of my React applications.
Folder Structure
/react-app
/build
/node_modules
/public
/src
/assets
/components
/contexts
/lib
/pages
/services
/styles
AppRoutes.tsx
index.tsx
react-app-env.d.ts
package.json
README.md
tsconfig.json
yarn.lock
Here's a quick overview of what are in these folders.
- /assets - images, logos.
- /components - components that are shared between multiple pages.
- /contexts - I keep all of the context components in a separate folder, to not confuse them with plain old react components. A common context I like to implement is UserAuthContext.tsx.
- /lib - When using a 3rd party library, let's say like Firebase for example, I like to put all of the initialization in a folder called lib. I'll then export the instance of that initialized library.
import firebase from "firebase/app";
firebase.initializeApp({
apiKey: process.env.REACT_APP_FIREBASE_API_KEY,
authDomain: process.env.REACT_APP_FIREBASE_AUTH_DOMAIN,
appId: process.env.REACT_APP_FIREBASE_APP_ID
});
export default firebase;
/pages - Pages are also react components, but they represent a page or screen of an app. These map 1:1 with a route in the AppRoutes.tsx file.
/services - All of my api methods are put in a folder called services. I like to do this so that I don't put the business logic of an API call directly into a component, and so that any component can easily reference a service that it needs.
/styles - I very rarely write custom css, instead opting to use a framework like tailwindcss. This styles folder is where my generated styles and any custom css goes.
AppRoutes - This file contains all the routes of my application. I've been using react-router for a while, and I like to have one file that contains all my routes so that I can see it all at a glance.
import React from "react";
import { Switch, BrowserRouter, Route } from "react-router-dom";
import { useAuthContext } from "./contexts/AuthContext";
import { Navbar } from "./components/Navbar";
import { LandingPage } from "./pages/LandingPage";
import { DashboardPage } from "./pages/DashboardPage";
export const AppRoutes: React.FC = () => {
const authAccount = useAuthContext();
return (
<BrowserRouter>
<div className="mt-8 w-4/5 max-w-6xl m-auto">
<Navbar />
</div>
<Switch>
{authAccount ? (
<AuthenticatedAppRoutes />
) : (
<UnauthenticatedAppRoutes />
)}
</Switch>
</BrowserRouter>
);
};
const UnauthenticatedAppRoutes: React.FC = () => {
return (
<React.Fragment>
<Route exact path="/" component={LandingPage} />
</React.Fragment>
);
};
const AuthenticatedAppRoutes: React.FC = () => {
return (
<React.Fragment>
<Route exact path="/" component={DashboardPage} />
</React.Fragment>
);
};
- index.tsx - This is your typical index file, where you render your React app to the document.
File Naming
My rule of thumb is the longer and more descriptive the file name, the better. For files that that export React components I use PascalCase, for everything else I use dash-case.
# PascalCase
/components/NavBar.tsx
/contexts/UserAuthContext.tsx
/pages/DashboardPage.tsx
# dash-case
/services/auth-service.ts
/lib/apollo-client.ts
I always prefer named exports instead of default exports. This makes it easier to search what I'm looking for in my editor.
Updates
I received some questions about this post, here are my responses:
Would be very interesting to see the structure inside of /components. Is there any nesting? A folder for each component with styles/test/... next to the component file itself?
I don't use any nesting in any of the folders. I also typically don't have a separate styles file, since I use frameworks like tailwind or bootstrap. The shape of of my components folder is like so:
/components
/__tests__
Button.test.tsx
Button.tsx
What do you do with one-off components? For example, a Contacts.jsx page has a ContactList component?
I will split up my page into sub-components, all within the same file as the page.
import * as React from 'react'
export const ContactsPage: React.FC = () => {
return (
<div>
<h1>Contacts</h1>
<ContactsList />
</div>
)
}
const ContactsList: React.FC = () => { ... }
Wrapping Up
This is the first post in a series of posts I will be doing. If you enjoyed this, please give me some hearts and leave a comment below. What else would you
As always, I'm open to recommendations.
Thanks for reading.
Top comments (16)
Great template, I follow something similar. The one thing that annoys me when looking up react projects on GitHub is they all use different directory structures.
This is one area I wish react was more opinionated about, even if it just involved recommended guidelines for project structure
It took me a long time to land on this. I tried several different styles, but this is the one that has worked the best for me thus far.
Interesting...
I have a similar approach. Would be very interesting to see the structure inside of
/components
. Is there any nesting? A folder for each component with styles/test/... next to the component file itself? A singleindex.ts
to re-export all components? Or aindex.tsx
in every components folder?As you can see, I think there are many different approaches to the
/components
folder. Would love a followup article or edit on that.Do you have any project where you applied that structure, that you can share? Would be interested in some API files.
Thanks :)
I don't use any nesting in any of the folders. The shape of of my components folder is like so:
I usually don’t have styles files in my apps. I use plain css frameworks like tailwind or bootstrap so there is not a separate styles file.
I see you have /components for shared components and /pages for the exact page matches, but what do you do with one-off components? For example, a Contacts.jsx page has a ContactList component. It’s not a shared component, but it’s not a page, either. I suppose in this design those components either are flattened into the one page component or live as a separate component but in the same file as the page. Is that correct?
That's correct! I will split up my page into sub-components, all within the same file as the page.
What if the component item does have a third-party library attach to it
eg.
import React from 'react';
import Zoom from 'react-reveal/Zoom';
const movieCard = () => (
....content
)
Is this the right structure if one component has some functionality on it
Hey great article, I wanted to ask you, how do you structure your graphql related files (client, queries, mutations, generated code)
I like to write my GraphQL queries and mutations in-line within the component file, since my queries are almost always 1:1 with the component that is using it. You can see this here: dev.to/farazamiruddin/an-opinionat...
As far as generated code, I keep a top level folder for all generated code and title it
__generated__
. All the auto-generated type definitions go in there.Awesome articles, man!
Thank you! I appreciate it 🙏🏽
Can't tell you how much I appreciate this. Simple, concise. Well done.
Thank you Faraz. I started a new project and follow your folder structure. I wonder how do you use AppRoutes.tsx? Is it just used in App.tsx like
<AppRoutes/>
.What about custom hooks? Does it go on services?
Really liked the template, but that's one thing I would have in mine (a hooks/ folder).
Interesting article! btw I have a question. Where do you put the files related to Redux like the actions and redcuers?
Thank you! I don't use redux, but if I did (or any other state management library for that matter), I would follow the same principle; flat folders, long file names.