Hacker News new | past | comments | ask | show | jobs | submit login
Ask HN: Well architected React and Node repos?
107 points by pixelready 5 months ago | hide | past | favorite | 65 comments
Does anyone have examples of what you consider to be well-architected react / node apps? Or just individual patterns you really like? I’m thinking about things like: - folder structure and naming - component breakdown and composition - routing patterns (front end and backend) - error handling - custom hook abstractions - protected routes / auth enforcement

For background: We’ve been building a number of SPA apps at work on a React / Vite / Fastify / tRPC stack and although I love the flexibility and devEx, I’ve found that it’s causing a certain amount of bikeshedding and ad-hoc architectural patterns to form, especially when we build similar features in parallel, so I’m curious how everyone else is leveling up their architectural sensibilities?




I'm a fan of feature oriented directory structures...

Instead of...

    tests
      auth
        login.test.ts
    controllers
      auth
        login.ts
    components
      auth
        login.tsx
    ...
You would have...

    feature
      auth
        login
          login.data.ts
          login.data.test.ts
          login.controller.ts
          login.controller.test.ts
          login.form.tsx
          login.form.test.ts
          ...
That, in my opinion should include tests... You can have shared components, etc... or break up sub-projects.. but within a given project, I prefer features/concerns over class/data type.

edit: In the above case, controller is really a higher order hook along with a higher order function component that will get call the hook, then pass the state to the separate component for render/events.

If you're doing server components, may want something similar but different depending on architecture or out of the box structures.


It’s interesting. I always go back and forth on this pattern. It makes sense to me logically, but where do you put your shared utils and such?


IMO, shared utils must be a library, like:

    features
        auth
            login
    libraries
        dates
        strings
        ...

I don't like to have a package / library called `utils`, `commons`, `shared` and other generic words that does not indicate me what's the context of this folder.


Cool, may start using that over shared, but may just use "!lib" I tend to use "!" in the beginning of directories I want elevated... in any case, thanks.


Why not both?

Move your pure function utilities to a feature-agnostic folder whenever it makes sense, and import them into your feature.

I agree that's where the problems begin though :)


    feature/shared/utils/foo.ts
    feature/shared/utils/format-date.ts
    feature/shared/ux/(template|region|etc)/foo.ts
Where ux are for components that may be referenced in multiple areas, or generic templates, etc. and shared are for utility methods, functions, etc.


I think the op is asking more on if a util is used across many features


tracker1 is saying that in that case there would be a feature named shared, which other features then reference.


yes... though, unlike above, I might be inclined to name the directory "!shared" to pump sorting to the top, which may feel weird/awkward.


In a commons folder?


Yes, this makes more sense, you have tests close to the code it test. Even integration tests should be somewhere in that hierarchy.

At the time I was even thinking that tests should be part of the same file where the component or feature is implemented. There were ways to make this work, but it required a lot of configuration at the time.


I don’t like seeing test files close to the code. It’s clutter and distracting. Some people do and that’s fair, but there’s no one way.


when i was working on java microservices a few years back at a major cruise line, the tests were of course in a completely separate folder structure. it would take ages to traverse the file tree. isn't that a major waste of time and really poor devex?


Your IDE should handle this kind of drudgery for you. The tests folder layout needn't be complex and deep either.


what about those of us who still prefer to use terminals, not just point and click GUIs?

relying on ever-more tooling feels too much like putting a band-aid over the problem to me.


What if a feature (auth page/module) has aspects that could be reused by other major features too, how/where would you place them?


Are they related to authentication and login? Reference them from their feature directory for what it is.


This is my preferred structure. The shape of the code should represent what it's trying to do. Optimize for peripheral vision.


This is the way.


Check out Tao of Node and Tao of React. It has worked pretty well for us, and is applicable in my opinion to other stacks as well, not just Node.

https://alexkondov.com/tao-of-node/

https://alexkondov.com/tao-of-react/


Looks interesting! Added to my reading list, thanks :)


Usually when I see someone else's repo, the structure doesn't fit my needs. My favorite pattern is putting everything into a single file until there's a clear reason to split it up, at which point the best structure will be obvious.


Yeah, this is my MO for personal projects, but I’ve found it can be messy for team dev, without a fairly opinionated folder scaffold.


Within teams, we've done fine submitting to Conway's Law until we get to the point where a different structure makes sense. Reduces merge conflicts that way.


One thought that is likely to be controversial... Prefer simpler and flatter directory structure over heavily nested and over-organized directory structure.

It's annoying to have a slight error in your import (ie features/segment/part/buttons/MyButton should be features/segment/portion/buttons/MyButton)

I've found through trial and error it's better to just have components/MyButton, maybe another level down


I have a fairly flat project that I’ve been managing for the past 5 years. It’s worked well for me.

I have found that deep nesting just makes me think more about unimportant stuff. It adds unnecessary friction. Also, naming is hard. More folders means more naming.


Well said


Everything is relative. This won’t scale on large websites with huge amounts of components. More useful is guidelines or tips on how to organize.


Scaled to at least 30k components for Facebook :) https://www.reddit.com/r/reactjs/comments/6al7h2/comment/dhg...


The post explicitly mentions it works because they invested a lot into internal tooling.

> It probably would be a bad idea unless you can build tooling that really benefits from this choice.


It is a tip on how to organize lmao


In the same way “no architecture” is a type of architecture, sure, throwing everything into one folder is technically organizing.


Good thing I didn't say throw everything into one folder


Remix has stacks to get started quickly: https://remix.run/docs/en/main/guides/templates#stacks


It’s probably not answering all your questions, but https://manuel.kiessling.net/2021/05/02/tutorial-react-singl... might be worth a read.

Also, although not React/Node, the thoughts laid out in https://manuel.kiessling.net/2012/09/28/applying-the-clean-a... have served me well over the years.


A well structured pnpm monorepo and a plugin system / architecture has made all the difference for us at Lowdefy [0].

Additionally we’ve architected a way to build complex web apps using config - not everyone’s cup of tea, but with a small team we are building a LOT of complex apps for customers. We are really happy with how this is scaling and we have all the flexibility we need on project.

The config first approach might be controversial, but have a look at the Lowdefy repo, after a few years of iterations it works well for us.

https://github.com/lowdefy


To add on as another example, I recently created a monorepo for three npm packages I publish that depend on each other (not in a circular dep way). It uses pnpm + turbo + changesets + syncpack to publish and manage the versions for cross-deps:

https://github.com/theogravity/datadog-transports


It’s worth adding that each customer app, is setup in its own monorepo which contains the app config and apps specific plugins. With a dependency on the main repo. Thus a updated framework version is easy to roll out to customer apps, while allowing custom components to be used where as needed.


Neat. Is lowdefy sort of like React Admin (if they were all-in on YAML)?


Pretty much. But you can do a lot more. For example, we’ve built advance CRMs which share data between 5 companies, many customer portals, order management apps, ticketing systems, and even an MRP like app, as well as many BI apps.


You can check out civitai's repo if you want smth for NextJS: https://github.com/civitai/civitai

Found it pretty useful for my usecase at least since most of my tech stack aligns with them, along with the component framework they use(Mantine)


What aspects of this codebase do you consider to be exemplary? I'm not familiar-enough with some of the libraries to offer a meaningful critique at a glance, but I'm also not seeing any tests.


this is a fantastic example


I'd say start with layers and over time evolve the repo.

For example, http, service, and repository layers. http has your request handlers and you parse those input DTOs or whatever here and call service. service has your business logic, and it calls out to repository (data layer) and once its done it returns the resulting DTO to http which just sends the response.

Over time you'll probably have issues where certain layers are overlapping in functionality. at this point you might want to try out features but this is going to blow out how much code you have.

I'd recommend focusing on solving the customer's problems without going insane.

If you don't care about your employer or you have a clueless manager (90% of managers out there) and just want a promotion, refactor a repo that's already working (even if not optimally tidy) to be 5x more complex and then get a new job.


When I contributed to Foxglove Studio, a robotics data visualization tool built in React and Electron, I found the codebase very easy to navigate. Without much prior JavaScript/TypeScript/React experience, I was able to prototype several new fairly sophisticated features. They've nicely decomposed the code into libraries, with just about the right level of abstraction to make it easy to extend. And given that it's built for visualizing streaming data, they've got performance figured out.

Unfortunately they ceased developing it in the open, but there's a lot to learn from the v1 codebase, and other related projects that continue to be open source.

https://github.com/foxglove/studio/tree/v1


Ah, there’s some nice patterns in the library code for sure. I’ll have to spend some time with it. Thanks for sharing!


I think there is a fair bit of personal tastes in the answers to these kinds of questions. Personally, I've become a fan of Josh Comeau's "delightful React file/directory structure" [1].

I think it makes a ton of sense, but again, I suspect there's a fair bit of personal preference in these kinds of things.

I'm eager to see what other styles and architectures people suggest!

[1] https://www.joshwcomeau.com/react/file-structure/


I don’t agree with everything in the filenaming (as you say, a lot of this is a matter of taste). But there are some excellent suggestions mixed in there around structure and organization. Bookmarked!


After many nodejs app iterations this will be my next nodejs architecture:

sql statements in ./sql/*

endpoint functions in ./endpoints/*

router files in ./routes

Subdirs under those that group things logically for that app

Auth functions in a separate server called by caddy forward auth like checkpoint401 which I wrote

User flow functions in a separate server like identoro which I wrote

Data validation in a separate server like youvalidateme which I wrote

I write big Postgres stored functions/procs and minimal sql in node

I gotta say though I’ll probably use Golang instead of node going forward, after building many node apps.


I’m a bit GoLang curious myself, but it seems like the modern react world is moving towards more tightly coupled monolithic full stack meta frameworks, with “use client” and “use server” directives sprinkled throughout the codebase.

Then again, I feel like a good backend-focused language, a nice templating system, HTMX, and the inevitable cross-platform view transitions support will become a very tempting option for the vast majority of CRUD focused web apps…



You can take a look at: https://github.com/ixartz/SaaS-Boilerplate, it should give you some inspiration to structure your React apps with folder structure, component breakdown.


Anything that doesn’t use default exports.


Even though I don't love Next.js and file-based routers in general, I'm a big fan of the cal.com repo: https://github.com/calcom/cal.com

Monorepo, modern packages, and the architecture seems well-considered.


This is a template of a well architected react app I came up with having developed quite a few https://github.com/venil7/react-open-architecture


This repo comes to my mind: https://github.com/outline/outline


The overall folder structure looks decent, but definitely seeing some of that emergent architecture syndrome that I’ve experienced. Like “menus” not being under “components” etc…


The React docs give some nice ideas. I organise with features and it honestly works so well for my needs but experimentation is so key with figuring out.



Is this React projects? Or Node.js projects?

Or projects that use both React and Node.js?


I’m open to patterns that are nice for the front end or the backend in isolation. Since we’re doing SPA, the two sides are fairly isolated other than sharing types through tRPC


Use clean architecture.


you cant well architect react or node.js code lol.


I just make it up as I go


Why not?




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: