Atomic Design with Next.js and React

Patrick Smith
The Tech Bench
Published in
3 min readJun 16, 2017

The Next.js framework has a fantastic balance of conciseness with capability. It makes full use of React, with client side rendering (read: fully dynamic web app), server side rendering (read: faster initial loads and better SEO), and probably best of all, is opinionated.

The first opinion is routing. All pages have their own separate files, and live in the pages directory. And then that’s it! There’s no setting up and maintaining React Router. Rename or remove a page’s .js file, and your routes follow.

The second is styling. It takes a little to get used to, but CSS styling is achieved with a block of CSS that lives inside your component. The benefits? CSS is rendered both on the client and server side. The library is light weight. Plus the full plethora of native CSS is supported, instead of relying on clever tricks to support media queries and CSS animation.

Third, it allows easy loading of data from an API before rendering. Simple add a getInitialProps method to your page component, run your asynchronous code, and Next will wait for it to complete before rendering and serving your page. There’s no React life cycle dance.

Lastly, it encourages putting your components in a dedicated components folder. It even gives you some to boot.

If we contrast with Brad Frost’s Atomic Design, we’ll see that pages are present in Next.js’s system seemingly under the same name. In Atomic Design, a page is a template that has been rendered with actual data. So in Atomic Design lingo, our template is our JavaScript file that lives in the pages folder, and our page is what we see loaded in our browser.

Atoms, and their combination as Molecules, are essentially our components. Whether you create subfolders components/atom/ and components/molecules/ to separate these two different kinds is up to you. What I would encourage, is to make these pure/dumb components that simply render their input props. That way they can be effortlessly reused.

In the middle of the Atomic Design system is the wily Organism. Made up of multiple Molecules or Atoms, the Organism is something more alive and more complex. Perhaps it talks to an API. Probably it manages state, and therefore is a smart or stateful component (i.e. a React.Component subclass). Our molecules are assembled together with purpose to form an organism.

Our pages/templates will be then made up of multiple organisms. Ideally our pages are simple light-weight containers that allow our organisms to do the bulk of the work.

So I suggest putting these more advanced components in an organisms/ directory, that sits alongside as peer to your pages/ and components/. Pages rely on organisms to do most of the heavy lifting, and load what is necessary for the user to get a fast initial experience. Organisms rely on molecules and atoms to render their assigned content. Their simplicity allows us to maximize reuse and modularity.

I have made react-organism to ease the creation of these organism components and speed up many common cases, such as loading asynchronous data from an API:

// organisms/Photos.js
import React from 'react'
import makeOrganism from 'react-organism'
import Photo from '../components/Photo'
export default makeOrganism(({ photos }) => (
<div>{
!!photos ? photos.map(photo => (
<Photo key={photo.id} {...photo} />
) : 'Loading photos…'
}</div>
), {
initial = () => ({ photos: null }),
load = async () => ({ photos: await fetch('/api/photos') })
})

I’ve also made it easier to quickly create these components, with create-react-organism:

yarn create react-organism Photos
# .[/src]/organisms/Photos/ is made with Photos.js, state.js, and index.js

If you would like to discuss I can be contacted on Twitter. You can also follow progress on GitHub. I’m interested to hear what you have to say too!

--

--

Patrick Smith
The Tech Bench

@concreteniche · Product designer for the web & Mac. Loves experimenting with React, Swift, and UX tools.