Lesson 3 of 2220 min read

Next.js Folder Structure Explained for Beginners

A complete walkthrough of the default Next.js project structure, covering app/, pages/, public/, components/, and lib/ and what each folder is for.

Author: CodersNexus

Next.js Folder Structure Explained for Beginners

When you open a freshly scaffolded Next.js project for the first time, the folder structure can feel unfamiliar, especially if you're coming from plain React or a different framework. Files like layout.tsx, page.tsx, and folders like app/, public/, and lib/ each carry specific meaning to Next.js — they aren't arbitrary names, they're conventions the framework actively reads and reacts to.

Understanding this structure early prevents a lot of later confusion. Where you place a file directly determines whether it becomes a route, a shared layout, a static asset, or an internal utility. This lesson walks through every major folder generated by create-next-app and explains exactly what role it plays.

Learning Objectives

  • Identify the purpose of every major folder in a default Next.js project.
  • Understand how the app/ directory relates to routing.
  • Distinguish between public/, components/, and lib/ and know what belongs where.
  • Recognize special files like layout.tsx, page.tsx, and globals.css.
  • Organize a growing project using conventional folder patterns.

Core Definitions

  • app/: The root directory for the App Router, where folder structure maps directly to URL routes.
  • public/: A folder for static assets (images, fonts, favicon) served directly at the root URL path without any processing.
  • components/: A conventional (not framework-required) folder for reusable UI components shared across pages.
  • lib/: A conventional folder for utility functions, API clients, or shared logic not tied to UI rendering.
  • page.tsx: A special file inside app/ that marks a folder as a publicly accessible route and defines what renders for it.
  • layout.tsx: A special file that defines shared UI (like a navbar or footer) wrapping a page and its nested routes.
  • globals.css: A global stylesheet typically imported once in the root layout to apply site-wide styles.

Detailed Explanation

At the root of a Next.js project, you'll find configuration files like next.config.js, package.json, and tsconfig.json (if using TypeScript) — these control build behavior, dependencies, and type checking, and rarely need manual editing when starting out.

The app/ folder is the heart of routing in the App Router. Next.js reads this folder's structure to generate your site's URLs. A folder named app/about/ with a page.tsx file inside becomes accessible at yoursite.com/about. The root app/page.tsx becomes your homepage at yoursite.com/. This is called file-based routing, and it means you rarely write manual route configuration — the folder structure IS the routing configuration.

Alongside page.tsx, you'll often see layout.tsx. A layout wraps its page and any nested pages with shared UI, such as a navigation bar or footer, without re-rendering that shared UI on every navigation — this is one of the App Router's key performance advantages over the older Pages Router.

The public/ folder holds static files — images, fonts, robots.txt, favicon.ico — that Next.js serves directly at the root URL without any transformation. A file at public/logo.png is accessible directly at yoursite.com/logo.png.

components/ and lib/ are not required by Next.js itself — the framework doesn't look for these folders specifically — but they're strong community conventions. components/ holds reusable UI pieces like buttons, cards, and modals that get imported into pages. lib/ holds non-UI logic: database connection helpers, API request functions, formatting utilities, and constants. Keeping this separation makes projects easier to navigate as they grow.

Diagram Description

Visualize a folder tree:

my-app/
├── app/
│ ├── layout.tsx (shared layout wrapping all pages)
│ ├── page.tsx (homepage → '/')
│ ├── globals.css (global styles)
│ └── about/
│ └── page.tsx (about page → '/about')
├── public/
│ ├── logo.png (→ served at '/logo.png')
│ └── favicon.ico
├── components/
│ ├── Navbar.tsx
│ └── Button.tsx
├── lib/
│ ├── db.ts
│ └── formatDate.ts
├── next.config.js
├── package.json
└── tsconfig.json

Comparison Table

Folder / FileRequired by Next.js?Purpose
app/Yes (App Router)Defines routes via folder structure; holds pages and layouts
app/page.tsxYes, per routeMarks a folder as a visitable route and defines its content
app/layout.tsxYes, at rootShared UI wrapping a page and its nested routes
public/Yes (convention)Static assets served directly at the root URL
components/No (community convention)Reusable UI components shared across pages
lib/No (community convention)Utility functions, API clients, shared non-UI logic
next.config.jsYesProject-wide configuration for builds, images, redirects, etc.

Next.js Practical Example

// app/layout.tsx — shared layout wrapping every page
import './globals.css';
import Navbar from '@/components/Navbar';

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        <Navbar />
        {children}
      </body>
    </html>
  );
}

// app/page.tsx — homepage content
export default function HomePage() {
  return <h1>Welcome Home</h1>;
}

// app/about/page.tsx — becomes accessible at /about
export default function AboutPage() {
  return <h1>About Us</h1>;
}

// components/Navbar.tsx — a reusable component, not a route
export default function Navbar() {
  return (
    <nav>
      <a href="/">Home</a>
      <a href="/about">About</a>
    </nav>
  );
}

RootLayout in app/layout.tsx wraps every page in the app with a shared Navbar and imports the global stylesheet once. Because layout.tsx wraps children, both HomePage (app/page.tsx) and AboutPage (app/about/page.tsx) automatically render inside this shared shell without needing to import the Navbar themselves. Note that Navbar.tsx lives in components/, not app/ — placing it inside app/ would risk Next.js treating its folder as a route, whereas components/ is purely for import, with no routing behavior attached.

Industry Examples

  • E-commerce sites organize app/ into folders like app/products/[id]/ for dynamic product pages, while keeping reusable elements like ProductCard and PriceTag in components/.
  • SaaS dashboards keep API request logic and authentication helpers in lib/ (e.g., lib/api.ts, lib/auth.ts) separate from UI code in components/ and app/.
  • Marketing agencies keep all brand assets — logos, hero images, downloadable PDFs — inside public/ so they're directly linkable without any build processing.
  • Content-heavy sites like blogs and documentation platforms use nested app/ folders such as app/blog/[slug]/ to map cleanly to their content structure.
  • Large teams enforce folder conventions like components/ui/ for design-system primitives and components/features/ for feature-specific components, layered on top of Next.js's own app/ routing convention.

Interview Questions and Answers

Q1. What determines the URL routes in a Next.js App Router project?

The folder structure inside the app/ directory directly determines routes. A folder app/contact/ containing a page.tsx file becomes accessible at /contact. This is called file-based routing, and no manual route configuration file is required.

Q2. What is the difference between page.tsx and layout.tsx?

page.tsx defines the unique content for a specific route and makes that folder publicly accessible as a URL. layout.tsx defines shared UI, like navigation or footers, that wraps a page and all of its nested routes without re-rendering on every navigation.

Q3. What is the public/ folder used for, and how are its files accessed?

The public/ folder stores static assets like images, fonts, and favicons that Next.js serves directly at the root URL without processing. A file at public/logo.png is accessed directly at /logo.png in the browser, without needing to reference the public/ prefix.

Q4. Are components/ and lib/ required by Next.js?

No, neither folder is a Next.js convention that the framework specifically looks for. They are widely adopted community conventions: components/ for reusable UI pieces and lib/ for non-UI utility logic, kept separate from the routing-sensitive app/ directory.

Q5. What would happen if you placed a component file directly inside the app/ directory instead of components/?

If the file follows a special naming convention like page.tsx, layout.tsx, or route.ts within its own folder, Next.js may treat it as part of routing. Regular non-special-named files inside app/ subfolders are generally fine, but the strong convention is to keep purely reusable UI outside app/ in components/ to avoid ambiguity and keep routing folders clean.

MCQs With Answers

1. Which folder determines the URL routes of a Next.js App Router project?

  1. public/
  2. components/
  3. app/
  4. lib/

Answer: C. app/

Explanation: The app/ directory's folder structure is read directly by Next.js to generate routes; each folder with a page.tsx becomes an accessible URL.

2. A file at public/banner.jpg is accessible in the browser at:

  1. /public/banner.jpg
  2. /banner.jpg
  3. /static/banner.jpg
  4. /assets/banner.jpg

Answer: B. /banner.jpg

Explanation: Files inside public/ are served directly at the root URL path, so public/banner.jpg is accessed at /banner.jpg without the 'public' prefix.

3. What is the role of layout.tsx in the App Router?

  1. Defines a unique page's content
  2. Provides shared UI wrapping a page and its nested routes
  3. Stores static images
  4. Configures the build process

Answer: B. Provides shared UI wrapping a page and its nested routes

Explanation: layout.tsx wraps a page and any nested routes with shared UI, like a navbar, without re-rendering that shared UI on every navigation.

4. Which folder is a community convention rather than a Next.js routing requirement?

  1. app/
  2. components/
  3. app/page.tsx
  4. app/layout.tsx

Answer: B. components/

Explanation: components/ is not read by Next.js for routing purposes; it's a widely adopted convention for organizing reusable UI, unlike app/ which directly powers routing.

5. What makes a folder inside app/ publicly accessible as a route?

  1. Adding any .tsx file inside it
  2. Adding a page.tsx file inside it
  3. Adding it to next.config.js
  4. Naming the folder 'route'

Answer: B. Adding a page.tsx file inside it

Explanation: A folder only becomes an accessible route when it contains a page.tsx file; folders without one are not directly visitable URLs.

Common Mistakes to Avoid

  • Placing static images inside components/ or app/ instead of public/, causing them to not be served correctly at a direct URL.
  • Assuming components/ and lib/ are special Next.js folders the framework enforces, when they're actually just conventions.
  • Forgetting that a folder inside app/ without a page.tsx file is not a visitable route, even if it contains other files.
  • Duplicating the Navbar or Footer inside every page instead of placing it once in layout.tsx.
  • Referencing public/ in the file path when linking assets, e.g. writing /public/logo.png instead of the correct /logo.png.

Interview Notes

  • app/ is read directly by Next.js for routing; its folder structure maps to URL paths.
  • page.tsx makes a folder a visitable route; layout.tsx provides shared wrapping UI without re-rendering on navigation.
  • public/ serves static files directly at the root URL, without a 'public' prefix in the path.
  • components/ and lib/ are community conventions, not Next.js requirements, for organizing UI and utility code respectively.
  • Root-level config files like next.config.js, package.json, and tsconfig.json control build and project-wide settings.

Key Takeaways

  • Next.js's app/ folder is not just organizational — its structure directly generates your site's routes.
  • layout.tsx and page.tsx are special, framework-recognized files with distinct responsibilities: shared wrapping UI versus unique page content.
  • public/ is the only place for assets meant to be served at a direct, unprocessed URL.
  • components/ and lib/ keep reusable UI and utility logic cleanly separated from routing-sensitive app/ code, a pattern that scales well as projects grow.

Summary

The default Next.js project structure is built around meaningful conventions rather than arbitrary folder names. The app/ directory directly powers routing through file-based routing, where page.tsx marks a route and layout.tsx defines shared wrapping UI. The public/ folder serves static assets directly at the root URL. components/ and lib/, while not enforced by Next.js itself, are strong community conventions for organizing reusable UI and utility logic respectively. Understanding what each folder does — and doesn't do — is essential before building out routes and features in later lessons.

Frequently Asked Questions

The app/ folder is the root of the App Router and directly determines your site's routes based on its folder structure. Each folder containing a page.tsx file becomes an accessible URL route.

public/ stores static assets like images and fonts that are served directly at the root URL without processing. components/ stores reusable React UI components meant to be imported into pages, and is not directly accessible via URL.

No. lib/ is a community convention for organizing non-UI logic like API clients, database helpers, or utility functions. Next.js does not specifically look for or require a lib/ folder to function.

Reference it directly from the root path without the 'public' prefix. A file at public/hero.jpg is accessed in your code or browser as /hero.jpg.

That folder will not become a visitable route on its own. It can still hold other files (like layout.tsx, components, or nested route folders), but without a page.tsx, there is no publicly accessible page for that exact path.

Yes, some projects colocate certain components inside specific app/ route folders for feature-specific components, while keeping globally shared components in a root-level components/ folder. Both patterns are valid; consistency within a project matters most.

globals.css holds site-wide CSS rules. It's conventionally imported once inside the root app/layout.tsx file so the styles apply across the entire application without needing to be re-imported on every page.

No. Unlike some other frameworks, the App Router requires no separate routing configuration file — the folder and file structure inside app/ is itself the routing configuration.

next.config.js is a root-level configuration file where you customize build behavior, such as image domains, redirects, environment variables, and other project-wide settings.

Non-UI utility functions, such as date formatting, API calls, or database helpers, conventionally belong in lib/. components/ should be reserved for files that return JSX and represent visual UI pieces.