Ask HN: Well architected React and Node repos?
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?
65 comments
[ 3.1 ms ] story [ 133 ms ] threadFound 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)
Or projects that use both React and Node.js?
https://alexkondov.com/tao-of-node/
https://alexkondov.com/tao-of-react/
Instead of...
You would have... 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.
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 :)
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.
relying on ever-more tooling feels too much like putting a band-aid over the problem to me.
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.
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.
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…
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 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.
> It probably would be a bad idea unless you can build tooling that really benefits from this choice.
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.
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
https://github.com/theogravity/datadog-transports
Monorepo, modern packages, and the architecture seems well-considered.
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
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/