A Better Way to Structure React Projects
8 min read
First off, if you don’t know what atomic design is, I’ll give a brief primer below but I suggest you go to Brad Frost’s website and check it out.
Atomic design is Brad Frost’s methodology for building design systems. The idea is that we can take the basic building blocks of living things and give our UI a hierarchical structure based on it.
Brad Frost defines five main stages of UI components:
Atoms are the simplest form of UI, consisting of things like headers, labels, input fields, buttons, etc.
Molecules are a combination of atoms that form more complex pieces of our UI, such as a search field with a submit button.
Organisms build on top of molecules and orchestrate larger parts of the UI. This can include a list of products, a header, forms, etc. Organisms can even include other organisms.
Templates are where our pages start to come together, giving context to all of our organisms and molecules by giving them a unified purpose. For example, a template for a contact page will have organisms for headers and forms, and molecules for text fields and navigation bars.
Pages, as the name implies, is our final page with all its content. The difference between pages and templates is that templates don’t provide any content.
Goal of This Article
I want to present a way to apply atomic design in your development workflow with the goal of making your code and project structure more maintainable, scalable, and intuitive.
Additionally, atomic design is a framework that can help bridge the communication gap between development and design. It is important that developers understand it so they speak to designers in a unified language.
When components are appropriately categorized, teams will be surprised to see how much more intuitive and organized their UI systems feel. Code is more maintainable, updates and refactors are easier, and on-boarding new designers and developers becomes a more efficient process.
Common Project Structure
Many of you are probably familiar with the folder structure below:
The idea here is that we try to keep components as “dumb” and as stateless as possible, while containers orchestrate our components and act as our pages.
I think we should get rid of this whole “container” vs. “component” concept for the following reasons:
- It’s not scalable. We only have two buckets to dump our UI in. What happens when we have 200 components and just two categories? Exactly.
- It’s not intuitive. What’s a container, really? Is it a page? Or is it just a stateful component? Where do the two meet?
- It’s a dev concept, not a design concept. How can we efficiently cooperate with designers if we are speaking a different language? Designers aren’t concerned with stateful vs. non-stateful, they are concerned with application and relationships. How is the component used, and how does it relate to the rest of the UI?
A Better Project Structure
Why don’t we structure our project according to the stages of atomic design?
Notice how we put pages outside of our components folder. Intuitively, we don’t put pages in the same category as the other four stages. Pages are the final presentation, not the individual components themselves.
Also, I typically create a
/forms folder inside the root organisms folder. Forms are super common so it’s a nice way to make your folder structure a bit more granular.
So, what do we gain here by making this small adjustment? Surprisingly, a lot!
- Unified design and dev language. It is much easier to collaborate with your design team now that you are using the same lingo across the board. For my devs using storybook out there, this is even more beneficial.
- Scalable folder structure. We now have refined categories for our components. It is much easier to keep our UI organized even if we have 200+ components.
- Minimal project context needed. Normally, a new developer needs to have a good amount of context on a project in order to find components they need. With atomic design, the language and structure are more universal, so it is much easier to say: “Well, a header is an organism, so let me check the organism folder.”
- Cleaner code. How, you ask? Well, atomic design forces you to better understand the relationship between your components. Even if you start with a big, messy, multi-functional component, refactoring is a breeze when you start thinking: “OK, where do I see organisms, molecules, atoms, etc.”
Congrats, you have a rock-solid folder structure for your next UI project. Is that all?
Let’s fast-forward a couple of weeks. You have a few atoms, a few molecules, life is good, you’re thinking: “This is working out great! Kris isn’t so dumb after all!”
But then you hit a roadblock… You are building a complex component and aren’t sure whether it’s an organism or a molecule. Can molecules have state? When does a molecule become an organism? For that matter, where is the line between an organism and a template? A template and a page?
The lines between stages can get fuzzy in practice, so in part 2, we will take a look into how we can define these lines in a React project.
That’s all for this part, thanks for reading!