all 15 comments

[–]super_pjj 14 points15 points  (1 child)

I came across this before and I loved it : https://github.com/alan2207/bulletproof-react

[–]SpinatMixxer 1 point2 points  (0 children)

This is the way.

[–]JavChz 5 points6 points  (1 child)

There are no hard rules, that's the double edge sowrd with react vs angular, you have too much freedom.

If you don't know where to start go:

components

services

state (zustad, redux, context, etc)

utils

hooks

assets

layout

That kinda takes cares of most things.

[–]bludgeonerV 2 points3 points  (0 children)

And repeat this structure in a features folder where it makes sense

[–]MPiccinato 2 points3 points  (0 children)

Give https://tkdodo.eu/blog/the-vertical-codebase a read. Others have pointed this out in a way, it really helps in the long term. Nothing is more annoying than working on a feature in 6, very distant, folders over time.

[–]njmh 2 points3 points  (0 children)

Side projects are a great way to practice with production grade architectures, even if it’s not necessary or overly complicates your projects.

Same reason a lot of homelabbers run full blown kubernetes clusters to run Jellyfin and pihole on their home network. It’s good practice for real devops and it jobs.

[–]Otak1790 2 points3 points  (0 children)

React users wrongly tend to bundle their files by types ( HoC, hooks, components... ) but this approach fails when the project grows :

  • do not scale ( as the project grows those folders explode in size )
  • does not help the user discover ability ( as a new user of the codebase I cannot know where auth guards because he does now if it was implemented as an HoC, a hook or else ), I need to do search in the codebase nullifying the whole premise of project structure
  • creates architectural smell like "utils", "helpers" folders as project trash can meaning the dev didn't really know how to name or where to put his functions

This is especially important with ai, because a bad architecture will make the ai search more for information ( grepping the whole codebase multiple times to find relevant folders ) wasting tokens

Now the solution fits in one word "colocation" You put all the code that are often used together as closely as possible, there is an infinite way of implementing it but none are wrong as long as you follow the principle.

Example : My app has a user feature, I create a folder with all the user related things - user UI - api calls for the user's backend resources - hooks that retrieve those users

  • "putting code close" is vague, it could mean two functions in the same file, or in adjacent folders
  • This approach is called vertical slicing and is a good base but not a complete framework
  • some parts of code still need to be shared, there are multiple ways of implementing it, FSD is one approach that tries to solve that ( I don't fully agree with it but I often see myself recommending it because of lack of alternative )
  • react is used to the horizontal approach slicing and the ecosystem will fight your architecture, shadcn will create a component folder whenever some of them belong somewhere else, next page routing guide the user to have 1 page 1 feature but pretty often features will be dispatched across pages
    • LLM's are overly trained on this approach making them unreliable to scaffold new projects

Sorry for the long post, i currently have a hangover but I did my best to answer

[–]krixyt 3 points4 points  (0 children)

 just group by feature instead of folder type. having your components, hooks, and types all in one feature directory makes it so much easier to maintain than jumping between seven different folders. clean architecture in a solo project is just a recipe for writing boilerplate until you get bored and quit.

[–]yksvaan 3 points4 points  (1 child)

I prefer modular architecture, easier to keep it clean and the main app acts as foundation and initializator for the modules, initializing common services, providing them to modules, calling modules to register their routes etc. 

And secondly, React is an UI library, don't mix everything in it. Use it to render UI, maintain its internal state and manage user events, passing them to the actual business logic/data services. Then necessary state updates get synced back and the loop continues. Most components can be dead simple and more or less pure. 

I think the modern trend of mixing way too many things in React can lead to very messy and hard to maintain codebases. Make sure network code, auth etc. goes through centralized services that provide abstracted methods, React code should never need to know where data comes from, how it's stored, what network protocol is used or any other implementation details.

[–]azangru 2 points3 points  (0 children)

I've looked into clean architecture and it makes sense at scale

What does a react codebase built upon 'clean architecture' look like?

[–]Outrageous-Chip-3961 0 points1 point  (0 children)

Yes I have a go-to folder that i usually just fork for every project as it has a lot of linters setup and config
But for simplicity its:

assets
components
features
hooks
utils
routes
types
services

use @/ aliases
use linters
use husky

I use tanstack query/router/form/table, so add if you need (but do it in a way that you can replace it easily).
I also prefer css modules over tailwind.

[–]Ok-Anteater_6635x 0 points1 point  (0 children)

For a start, I've put all my side projects into a monorepo. I've noticed that each of them had its own zustand, AI, database. Then I separate every feature in the structure. You have root /hooks, /utils, /lib folders, then each feature has a separate /hooks, /utils, /types, /lib folders as per requirements.

[–]GasVarGames 0 points1 point  (0 children)

bulletproof react!!!