DEV Community

loading...
Cover image for How I structure my mid-size NextJs projects

How I structure my mid-size NextJs projects

Joseph Mukorivo
Software Engineer | Python and JavaScript Developer | Writer | DevOps Enthusiast
・2 min read

As you know React is not an opinionated library. What that means is that there is no clearly defined way of doing things, for instance, React doesn't force you to structure your projects in a certain way. All that is left for you the developer.

Here we are going to be using NextJS, which is a framework built on top of React. NextJS helps us by optimizing our app through code-splitting, image optimization, static site generation, server-side rendering, etc. In this article, we are ignoring all this awesomeness as it is not the focus of the article. I recommend looking at NextJs docs if you are new to it.

Below is a high-level folder structure of our app.

📦src
┣ 📂charts
┃ ┣ 📜index.js
┃ ┗ 📜sunburst.js
┣ 📂components
┃ ┣ 📂breadcrumb
┃ ┃ ┣ 📂styles
┃ ┃ ┃ ┗ 📜breadcrumb.js
┃ ┃ ┗ 📜index.js
┃ ┗ 📜index.js
┣ 📂containers
┃ ┣ 📜index.js
┃ ┗ 📜navbar.js
┣ 📂fixtures
┃ ┗ 📜data.json
┣ 📂lib
┃ ┗ 📜gtag.js
┣ 📂pages
┣ 📂public
┃ ┣ 📂fonts
┃ ┃ ┗ 📂Arial
┃ ┣ 📂icons
┃ ┣ 📂images
┃ ┃ ┣ 📂svg
┃ ┣ 📂videos
┃ ┣ 📜manifest.json
┃ ┣ 📜sitemap.xml
┃ ┗ 📜sw.js
┣ 📂scripts
┃ ┗ 📜generate-sitemap.js
┣ 📂styles
┣ 📂utils
┣ 📜.env
┗ 📜next.config.js

Yes I know, this looks a bit complex. Let's demystify it by looking at each folder separately.

Charts

Usually, my applications have some charts to visualize data. All my charts will be located here and exported from an index.js file that acts as a barrel.

Components

This is probably the most interesting folder because that's where you will spend most of your time in. For each component in my components, I create a separate folder for it, and in that folder I create an index.js file to export the component and a separate folder for the component styles. There is also an index.js file in the components folder that exports all the components. If you then want to import say a <Button /> component you will do it like so import { Button } from 'components'

Containers

This folder is also important. Components acts as atoms and if we combine those atoms we form elements. For example if we combine links, buttons and grids components(atoms) we can create a navbar container(element). This makes it easy to compose to UIs. These containers are imported in pages to form the complete webpages.

Fixtures

This folder contains some static data like a list of all links.

Lib

Files in this directory acts as an interface between our application and external libraries like google analytics.

Public

This folder host the static files like images, fonts, videos, sitemaps, service workers, etc.

Scripts

This folder contains some scripts that I usually run at build time like generation of sitemaps.

Styles

Global styles are stored in this directory.

Utils

Functions that I want to be shared across the whole application are stored in this directory.

I hope this article helped you, let me know if you have another folder structure that you want me to look at. I will be happy to try it out.

Discussion (17)

Collapse
clamstew profile image
Clay Stewart

It’s a lot of index.js. Do you ever find that’s inconvenient in the code editor tabs? My team did and no longer use index.js files.

Collapse
stradivario profile image
Kristiqn Tachev

This is called Barel export and it helps with tree shaking and bundle resolution. In large project it helps to bundle it faster. I do recommend to use barel exports.

Regards!

Collapse
josemukorivo profile image
Joseph Mukorivo Author

I also like the convenience of importing components from components instead of components/button that's why I sometimes find myself using these index files

Collapse
aspiiire profile image
Aspiiire

For my projects instead of index.js I call them the name of the folder example header/header.js it is more clean and you'll not get confused

Collapse
endrureza profile image
Endru Reza

how is it clean ? header/header its like repeatition. is it gonna be

import Header from 'header/header.js'
Enter fullscreen mode Exit fullscreen mode

wow

Thread Thread
aspiiire profile image
Aspiiire • Edited

If you use default export it would be, you don't need to explicitly say import Header, in my prospective it is not needed

import 'header/header.js';
Enter fullscreen mode Exit fullscreen mode

Yes you are repeating the name, you are right, but you solve the problem of having multiple index.js.

As example you have main.js file that is importing all the components:

import 'header/index.js';
import 'footer/index.js';
import 'leftbar/index.js';
import 'somethingelse/index.js';
Enter fullscreen mode Exit fullscreen mode

Now if in my editor I have all this files open I see 4 index.js files, if I call the in this other way:

import 'header/header.js';
import 'footer/footer.js';
import 'leftbar/leftbar.js';
import 'somethingelse/somethingelse.js';
Enter fullscreen mode Exit fullscreen mode

In my tabs I see header, footer, leftbar etc... I have used it and I found myself great with it, but as always it is a matter of preference, there is no you must do this or that, you are free to choose any style you like

Collapse
hisuwh profile image
Henry Ing-Simmons

Organising code by feature is the way forward. I shudder whenever I see /components...

Collapse
robinlloyd profile image
Robin

Do you have any examples of organising code by feature? I'm curious as to how that goes as I very much have a similar approach to this article at the moment, but I'm definitely open to trying different methods.

Collapse
robinlloyd profile image
Robin

Ignore me, I should learn to google things more haha. I'm guessing you mean something along the lines of this right? reactjs.org/docs/faq-structure.htm...

That's interesting, I'll have to try that approach in my next project. It can be super frustrating sifting through a huge components directory so having one common directory for anything shared and everything else being at a page or feature level could look more organised.

Thread Thread
hisuwh profile image
Henry Ing-Simmons

Yh this is it exaxtly. I haven't done a lot of next.js so I'm not sure how this works with pages, but essentially you have a folder for a feature, say like "user" then within that you can have your UserProfile component, your EditProfile component and whatever else all conveniently co-located. I also a proponent of having your tests next to their subject files so they're easy to update.

If these folders grow too large you can break them down into sub features.

Collapse
josemukorivo profile image
Joseph Mukorivo Author

Seems to be maintainable, but how do you deal with shared and small components like buttons?

Collapse
hisuwh profile image
Henry Ing-Simmons

As Robin has alluded to you can have a common folder. I in fact have a fairly large common folder, broken down into sub-features - e.g. common/buttons. I also don't like the index.js approach as someone else has mentioned so I would have common/buttons/SaveButton.js, common/buttons/CancelButton.js etc. Then one index.js file in buttons to export these.

For common you can even then add a webpack alias so you can import these from anywhere without lots of ../../, e.g. import { SaveButton } from "@common/buttons";

Collapse
ivanjeremic profile image
Ivan Jeremic

index.js is bad. Try a project without will be much cleaner.

Collapse
endrureza profile image
Endru Reza

do you have any article that support your opinion as to why using index.js is bad ?

Collapse
ivanjeremic profile image
Ivan Jeremic

Index.js is not meant to be used like that, first of all the guy who created node was at first unsure to make index behave like in the browser, this is what I read somewhere, also only because React is a component framework it doesn't mean every component needs to be an index, there is no benefit at all it messes with your DX in the editor the project gets more complex and it is simple not meant to be used like that.

Collapse
josemukorivo profile image
Joseph Mukorivo Author • Edited

Yes makes sense, you can use just one index file to export all components from the components directory.

Collapse
ivanjeremic profile image
Ivan Jeremic • Edited

What I do is represent all the pages I have in the pages directory with a folder inside components, so if I have a News, Contact, About inside my pages dir. I have inside /components for all them a folder called also /News, /Contact, /About and inside them there are just react components who belong to them, very important at this point is to never create folders at this level just drop the components inside the folder of the page, if you have components used by multiple pages or subcomponents for this I have a folder shared /components/shared. To keep everything clean as possible I recommend Recoil.js for state or Jotai. I work on this structure for over an year now and I had never a cleaner project everything just makes sense when you look at it.