When it comes to starting a new project that you know is going to be big, a sound file structure is a must to nail in the first setup and you as a senior developer need to set up the file system so your team knows how to develop every feature.
In this article I’m going to go through 3 examples: e-commerce, blog, and social media. Indicating which file structure is best for them. This is my opinion and I haven’t asked ChatGPT to write this for me so take it with a pinch of salt and use your own judgement. By the end you’ll know: folder layout, what goes in Redux, how e-commerce / blog / social differ.
The first and most important advice that I want to give you is that you don’t use the frequently messy: pages, services, css, components, hooks, store… structure, I know you’ve used it many times in the past but it is crucial that you structure with these 2 big ideas in mind: features and shared code. Features indicate what the website does, cart, product list, checkout for e-commerce and blog and users for a blog, and social feed and post and user wall for a social media site. After separating the main features you want to expose what is shared within the app: components, utils, api, config. After that you want to have misc folders: types, store and assets.
If you’re using a framework like Next.js or React Native you will have a handy app folder for your url structure, this is very useful to have the page components grouped by url, but you should still use the features structure. What you don’t want to have in the app folder is shared components, and code belonging to the state. Pages should read like a table of contents 10 to 30 lines that import from the features folder. It’s a good place to have the server side file structure but you should keep the reusable functions in the shared folder (making sure these are server side functions only).
A good folder structure for a feature
a components folder for shared components within the feature only, and the same vibe for hooks, types, tests and api folders, but remember to move to the shared folder functions that are used across several features.
A good folder structure for the shared folder can be
- ui/ where your atomic components live: buttons, headings, cards… but specific feature components do not: add to cart button, number of likes badge, user card…
- libs/ where your plain functions live, single file for each and if you want add folder for all the tests or have them near your functions.
- api/ where your API calls live, these are the lowest level api calls live, the GETs and POSTs that just receive the parameters to send and return formatted or ready to be consumed data. These functions are not to be confused with the data layer api functions which make use of a server side cache and can do data manipulation, these should be the ones communicating with that (GraphQL…). These functions should be in charge of the auth headers and error handling. Do not put the server side functions: getUserByID or checkout, they should live in the features folder.
- hooks/ useMediaQuery, useDebounce, useLocalStorage. Truly global logic. Tests can live in a common folder or with each hook.
- types/ Only global types: User, Product, ApiError. Feature types should live within each feature: CheckoutError, ProductToBuy…
- config/ and constants/ files that use the process.env logic, never store actual API keys here.
- styles/ themes, global.css, mixins, breakpoints, variables. Component CSS should live in the features folder.
- public/ for files accessed via an absolute url
- assets/ for files imported in the code, like SVGs
State management
A good folder structure if using Redux can be to add a state/ folder to the project with an index file, a rootReducer and hook files and then having .slice.ts .selectors.ts and .types.ts for each feature. These files get wired together in the state/ folder’s files. You should also add a ui state slice for things like modal opened, side drawer, themes…
What a senior developer should know is what goes and doesn’t go into the state, when we have social media posts that need to be kept in the state for backwards and forwards navigation and like and comment, we do need to keep them in a global state, when we have a blog post that doesn’t have any interaction we should use server side rendering and not store it in the state. We should also not store the value of an input and update it on every character entered.
Another good practice is to put cross-cutting Redux middleware and listeners in a central store/ (or shared/store/) layer, and keep feature folders focused on slices, selectors, and UI, not one-off side effects scattered across components.
Different examples can be found on my personal blog:
https://raypoly.netlify.app/blog/howToOrganiseAComplexReactProject
I hope you’ve liked this article and let’s see each other again on the nets.
Top comments (0)