Next.js Project Structure

2 weeks ago 14
ARTICLE AD BOX

I am new to the world of web development and am getting started with developing a website using Next.js and Typescript. I have read the documentation and resources for TypeScript and Next.js to achieve my goal, and I am enjoying the development process. However, there was one question that haunted me from the beginning: how should the file structure of my website be organized?

This is the structure of a blank Next.js project bootstrapped with create-next-app :

. ├── app │   ├── favicon.ico │   ├── globals.css │   ├── layout.tsx │   └── page.tsx ├── eslint.config.mjs ├── next.config.ts ├── next-env.d.ts ├── node_modules (very HUGE folder) ├── package.json ├── package-lock.json ├── postcss.config.mjs ├── public │   ├── file.svg │   ├── globe.svg │   ├── next.svg │   ├── vercel.svg │   └── window.svg ├── README.md └── tsconfig.json

However, looking at other open source projects and examples, I understand that a common convention is to keep the app directory purely for routing and store all application code in shared folders at the project root, like this:
One of the proposed project structures from the Next.js documentation.

This is the structure I chose for my project folder.

What counts as a "component"? Should the components folder only contain UI elements (navbar, footer, hero, etc.) and its related logic, or can I also put non UI-related code in it?

Where do hooks go? Should they live in a top-level hooks/ folder, or inside components/hooks/?

What is the lib folder for? Since I'm managing dependencies with npm, what kind of code belongs in lib/? Would it be appropriate to put my hooks there?

Finally, here's my project structure:

. ├── app │   ├── globals.css │   ├── layout.tsx │   ├── manifest.ts │   └── page.tsx ├── components │   └── ui │   ├── animated-size-container.tsx │   ├── background.tsx │   ├── badge.tsx │   ├── button.tsx │   ├── content.ts │   ├── status-badge.tsx │   ├── footer.tsx │   ├── hero-old.tsx │   ├── hero.tsx │   ├── icons │   │   ├── facebook.tsx │   │   ├── github.tsx │   │   ├── index.tsx │   │   ├── linkedin.tsx │   │   ├── loading-spinner.tsx │   │   ├── nucleo │   │   │   ├── book2fill.tsx │   │   │   ├── cursor-rays.tsx │   │   │   ├── diamond-turn-right-fill.tsx │   │   │   ├── expanding-arrow.tsx │   │   │   ├── life-ring-fill.tsx │   │   │   ├── microphone-fill.tsx │   │   │   ├── referred-via.tsx │   │   │   └── users-fill.tsx │   │   ├── twitter.tsx │   │   ├── unsplash.tsx │   │   └── youtube.tsx │   ├── max-width-wrapper.tsx │   ├── menu-item.tsx │   ├── nav │   │   ├── content │   │   │   ├── graphics │   │   │   │   ├── analytics-graphic.tsx │   │   │   │   ├── links-graphic.tsx │   │   │   │   └── partners-graphic.tsx │   │   │   ├── product-content.tsx │   │   │   ├── resources-content.tsx │   │   │   ├── shared.tsx │   │   │   └── solutions-content.tsx │   │   ├── index.ts │   │   ├── nav-mobile.tsx │   │   └── nav.tsx │   ├── nav-wordmark.tsx │   ├── placeholders │   │   ├── button-link.tsx │   │   ├── cta.tsx │   │   └── logos.tsx │   ├── popover.tsx │   ├── styles │   │   ├── fonts │   │   │   └── satoshi │   │   │   ├── license.txt │   │   │   ├── Satoshi-Black.ttf │   │   │   ├── Satoshi-Bold.ttf │   │   │   └── Satoshi-Variable.woff2 │   │   └── fonts.ts │   ├── svg-grid.tsx │   ├── svg-logo.tsx │   ├── svg-wordmark.tsx │   └── tooltip.tsx ├── components.json ├── eslint.config.mjs ├── lib │   ├── hooks │   │   ├── index.ts │   │   ├── use-copy-to-clipboard.ts │   │   ├── use-media-query.ts │   │   ├── use-resize-observer.ts │   │   ├── use-scroll-progress.ts │   │   └── use-scroll.ts │   ├── rich-text-area │   │   ├── icons │   │   │   ├── at-sign.tsx │   │   │   ├── heading-1.tsx │   │   │   ├── heading-2.tsx │   │   │   ├── hyperlink.tsx │   │   │   ├── image-icon.tsx │   │   │   ├── index.tsx │   │   │   ├── text-bold.tsx │   │   │   ├── text-italic.tsx │   │   │   └── text-strike.tsx │   │   ├── index.tsx │   │   ├── rich-text-provider.tsx │   │   ├── rich-text-toolbar.tsx │   │   └── variables.tsx │   └── utils │   ├── constants │   │   ├── index.ts │   │   └── main.ts │   ├── functions │   │   ├── capitalize.ts │   │   ├── cn.ts │   │   ├── fetcher.ts │   │   ├── index.ts │   │   ├── nformatter.ts │   │   └── urls.ts │   ├── index.ts │   └── README.md ├── next.config.ts ├── next-env.d.ts ├── node_modules (HUGE folder) ├── package.json ├── package-lock.json ├── postcss.config.mjs ├── public │   ├── android-chrome-192x192.png │   ├── android-chrome-512x512.png │   ├── favicon-dark.png │   └── favicon-light.png ├── README.md ├── tailwind-config │   ├── tailwind.config.ts │   └── themes.css └── tsconfig.json

Can you help me fix this mess? I want to learn.

Thank you

Read Entire Article