We Used Atomic Design as Project Structure on Production – How It Went

Atomic design on production stage.

Krzysztof Podobiński




Krzysztof Podobiński
Krzysztof Podobiński
Mar 3, 2021
min read

We used Atomic Design in production. I highly suggest checking out Brad Frost Atomic design explanation before reading this, especially if you don’t know what Atomic Design is. It’s worth mentioning that even though our implementation was mostly done in react, styled-components and typescript, Atomic can be achieved in any technology.


To explain why we decided on Atomic I would like to introduce our problem and use case.

  • Components have to be shared between existing apps (components are shared between them).
  • Components had to meet design criteria.
  • We wanted to create components fast.
  • The library must be in its own repository.
  • We knew that there would be a lot of components (100+).
  • We wanted to build components in isolation (storybook).
  • The project structure and component explorer must be easy to navigate.

We had to choose a project structure but most of the blueprints are prepared for whole apps, not just a component library.

Our business requirement wa to divide it into base components like buttons, inputs, containers, and more complex components according to their features.  That is not a bad idea but it can be difficult to come up with naming if the library has 100+ components.  Browsing such libraries is not the easiest task either so we had to keep that in mind.

Apart from that, organising in by feature would be great but in general we wanted our components to be unaware of any business logic or requirement. Focusing on what the component has to do at one time would mean sacrifices for any future uses in a different scenario.

So we started thinking... Maybe it’s the perfect case to use Atomic Design? 🤔


While working for a while with atomic, I started to notice some trade-offs. As developers, we can only be aware of it, making sure we can use it to our advantage.


Easy to navigate

We describe the complexity of components using atomic level which tells us how complicated components are used inside.For example, when you see a form component with simple inputs you can be 100% sure that it is molecule level component in the form directory.

Business complexity described by design

You can tell how big components are, without looking into the code. If a component is some kind of button, this will be an atom component.

Encourages splitting components

You may have to split components or group them because you can only use the max of 2 levels below. This forces you to look at another similar part in the design and build a component that you can reuse later.

Very high reusability

Because you split your components, you will find yourself using them a lot. Additionally, instead of implementing another similar version, you will add functionality to an existing one.


As I described above, atomic encourage the creation of small components, so testing should be easy if we don’t have to deal with overloaded organisms. Try to keep your test as isolated as your component and test external functions in isolation too.When you want to test styling check visual testing - use snapshots.


Vertical scaling is limited

We can go bigger and bigger but we can’t go smaller if something is an atom. It has happened to us a few times, that some atoms components started to have a lot of logic (most props and styles related). Going up in hierarchy is not easier either. You will find yourself in a lot of semantic conflicts like molecule importing a molecule. Most of these issues can be resolved using variants but this feels like dodging a problem and not resolving it.

Newcomers will be overwhelmed

Newcomers will have to understand how to create components that happened to us. Just be patient and review their mistakes (keep an eye on atomic level semantics).

Splitting components can feel like additional work

This sometimes feels like doing unnecessary work, because you are just wrapping a few components into a more complex one, but this as described above, keeps your project easier to navigate and development speed is increased each split.

Not consistent designs are hard to code & maintain

If you have to support N variants (e.g. input and buttons) this can be very hard and will lead to overloaded atoms, and molecules.

What is tricky

Keeping atoms small

We ran into an issue where atoms started to have a lot of props but most of them were related to styling. Implementing another atom (ex. button, list) with the same code doesn’t feel like a great solution. We decide on restyling the components, fromDescriptionList atom we created InlineHorizontalList which was the same component but styles were handled differently.That solved our problem with overloaded styling and we still keep the atomic level.

Description List
Inline Horizontal List

Organisms and Pages can have a lot of code and props

Moving styles props to variants so basically we get a re-styled version of the component. We can omit some props doing it this way (we omitted most of the props that variant was changing).

More complex components might need a many props to be used by an end-user. In that case moving style and config props to variants, and letting them use pre-configured variants solved the problem. The other thing we can do is handle obvious scenarios like using local state management (React’s useContext) or moving code to external functions (ex. React Hooks) where code is external from the component.

Implementing layouts

Implementing layouts, without components inside, seems odd at the beginning, because we are used to going straight to page level. Implementing the layout can be done using a few patterns like named childsand props.

The hardest part is actually developing them, because we can’t have real components inside. That’s why we decided to create a small helper for that, which was only used to show layout in isolation. It was just a div element that was always filling the parent, each element had different border color so telling when the slot ends were easy.

Helper (white blinking is because of reloading), notice border-color changes

What we could do better

We could’ve sacrificed a bit of atomic semantics and adjust atomic to our needs. Starting to separate code to variants much earlier would also be helpful. From the component library side, moving styles to variants is easy, but components are shared between different projects it’s better to be safe than sorry, as requesting changes in external, dependant projects might me tricky.


Atomic is great, but it is far from being a perfect solution. You need specific use case for it. (ex. component library, multiple frontends with sharable components).  Sometimes, splitting big components into smaller ones fitting atomic semantics is hard and messing it up hurts while developing. Looking at it from another perspective, this is a great validation tool that you probably did a bad job splitting a design into components.

In my opinion, the biggest advantage is that atomic development feels rapid fast later in the development cycle, although the start can be a bit rough. Creating components without context encourages high reusability (this speeds up later development by a lot). That was very noticeable for me after working with it for a while.

I highly suggest using atomic as a baseline guideline for creating your own design system that will fit your needs.


What’s a Rich Text element?

The rich text element allows you to create and format headings, paragraphs, blockquotes, images, and video all in one place instead of having to add and format them individually. Just double-click and easily create content.
  • test
  • test
  • test

Static and dynamic content editing

  1. xxx
  2. yyy
A rich text element can be used with static or dynamic content. For static content, just drop it into any page and begin editing. For dynamic content, add a rich text field to any collection and then connect a rich text element to that field in the settings panel. Voila!

How to customize formatting for each rich text

Headings, paragraphs, blockquotes, figures, images, and figure captions can all be styled after a class is added to the rich text element using the "When inside of" nested selector system.



Krzysztof Podobiński
Mar 3, 2021
min read