Next.js Lesson 4 – Folder Structure | Dataplexa
LESSON 4

Folder Structure

Master Next.js project organization and understand how folders control your application's behavior and routing.

Next.js has strong opinions about how you organize your code. Unlike plain React where you can put components anywhere, Next.js uses folder structure to determine routes, control rendering, and optimize your application.

The NewsWave team needs a well-organized project that scales from a dozen articles to thousands. Your folder structure becomes the blueprint for both your application's URLs and its performance characteristics.

App Router vs Pages Router

Next.js 13 introduced the App Router — a new way to organize your application. You'll see both patterns in the wild, but App Router is the future.

App Router (New)

Uses app/ directory. Server Components by default. Better layouts and loading states.

Pages Router (Legacy)

Uses pages/ directory. Client Components. Still supported but not recommended for new projects.

We'll focus on App Router since that's what modern Next.js applications use. But understanding both helps when you encounter older codebases.

Core Folder Structure

When you run create-next-app, Next.js creates a specific folder structure. Each folder has a purpose.

NewsWave Project Structure
📁 newswave/
📁 app/ ← App Router pages
📄 layout.js ← Root layout
📄 page.js ← Homepage
📄 globals.css
📁 public/ ← Static assets
📄 favicon.ico
📄 logo.png
📁 components/ ← Reusable components
📁 lib/ ← Utilities & data
📄 package.json
📄 next.config.js

The app/ directory is where the magic happens. Every folder inside becomes a route. Every special file controls behavior.

Special Files in App Router

Next.js reserves certain filenames for specific purposes. These aren't arbitrary — they're how Next.js understands your application structure.

File Purpose Required?
page.js Makes the route publicly accessible Yes
layout.js Shared UI for this route and children No
loading.js Loading UI during data fetching No
error.js Error UI when something breaks No
route.js API endpoint (GET, POST, etc.) No

Without page.js, your folder is just organizational. Add page.js and boom — it becomes a route users can visit.

// app/articles/page.js — Creates /articles route
export default function ArticlesPage() {
  return (
    <div>
      <h1>NewsWave Articles</h1>
      <p>Browse our latest stories</p>
    </div>
  )
}
localhost:3000/articles — NewsWave

What just happened?

The app/articles/ folder becomes /articles URL route. The page.js file makes it accessible to users. Without page.js, visitors would get a 404.

Try this: Create nested folders like app/category/tech/page.js for /category/tech routes.

NewsWave Folder Organization

Here's how we'll organize the NewsWave project for maximum scalability and developer experience:

NewsWave Complete Structure
📁 newswave/
📁 app/
📄 layout.js ← Nav, footer, global styles
📄 page.js ← Homepage with featured articles
📄 loading.js ← Global loading spinner
📁 articles/ ← /articles route
📄 page.js ← Articles listing
📁 [slug]/ ← /articles/breaking-news
📄 page.js ← Individual article
📁 category/
📁 [name]/ ← /category/tech
📄 page.js
📁 search/
📄 page.js
📁 api/ ← API endpoints
📁 articles/
📄 route.js ← GET /api/articles
📁 newsletter/
📄 route.js ← POST /api/newsletter
📁 components/
📄 Header.js
📄 ArticleCard.js
📄 SearchBar.js
📁 lib/
📄 articles.js ← Mock data & utils
📄 utils.js
📁 public/
📄 logo.png
📄 favicon.ico

Notice how folder names become URLs. The [slug] and [name] folders use square brackets — those are dynamic routes that accept parameters.

Route Groups and Private Folders

Sometimes you want to organize folders without affecting URLs. Next.js provides two special folder patterns:

Route Groups (folder)

Organize routes without affecting URLs. (marketing) folder ignored in URLs.

Private Folders _folder

Opt out of routing. _components folder never becomes a route.

// Route Groups — organize without URL impact
app/
├── (marketing)/           // ← Parentheses = route group
│   ├── about/
│   │   └── page.js       // → /about (not /marketing/about)
│   └── contact/
│       └── page.js       // → /contact
└── (news)/
    ├── articles/
    │   └── page.js       // → /articles
    └── category/
        └── page.js       // → /category

// Private Folders — never become routes
app/
├── _components/          // ← Underscore = private
│   ├── Button.js        // Private component
│   └── Modal.js
├── _utils/
│   └── helpers.js       // Private utilities
└── articles/
    └── page.js          // → /articles (public route)

Route groups help you organize code by feature area. Private folders keep implementation details out of your routing system.

Component Organization Patterns

Beyond the app/ directory, you need patterns for organizing reusable code. Here are three proven approaches:

1. Flat Components Folder

components/
├── Header.js
├── ArticleCard.js
├── SearchBar.js
├── Newsletter.js
└── Footer.js

Best for: Small to medium projects with < 20 components.

2. Feature-Based Folders

components/
├── layout/
│ ├── Header.js
│ └── Footer.js
├── articles/
│ ├── ArticleCard.js
│ └── ArticleList.js
└── ui/
├── Button.js
└── Modal.js

Best for: Medium to large projects with clear feature boundaries.

3. Colocation (Recommended)

app/
├── _components/
│ ├── Header.js ← Global components
│ └── Footer.js
├── articles/
│ ├── _components/
│ │ └── ArticleCard.js ← Article-specific
│ └── page.js
└── search/
├── _components/
│ └── SearchForm.js ← Search-specific
└── page.js

Best for: Any size project. Components live near the features that use them.

Colocation wins because it reduces the mental overhead of finding related code. When you're working on the search feature, everything you need is in the search/ folder.

Public Folder and Static Assets

The public/ folder serves static files directly from your domain root. No processing, no optimization — just raw files served at lightning speed.

// Files in public/ are served from domain root
public/
├── logo.png              // → yoursite.com/logo.png
├── favicon.ico           // → yoursite.com/favicon.ico
├── robots.txt           // → yoursite.com/robots.txt
└── images/
    └── hero-bg.jpg      // → yoursite.com/images/hero-bg.jpg

// Use them in components like this:
<img src="/logo.png" alt="NewsWave Logo" />
<link rel="icon" href="/favicon.ico" />

Warning: Static Assets

Don't put user-uploaded content in public/. It's part of your codebase and gets deployed with your app. Use cloud storage (AWS S3, Cloudinary) for dynamic images and files.

For NewsWave, public/ holds the logo, favicon, and any static images that are part of the design. Article images would come from a CDN or cloud storage.

Configuration Files

Your Next.js project root contains several configuration files that control build behavior, dependencies, and development experience:

Configuration Files
📄 package.json ← Dependencies & scripts
📄 next.config.js ← Next.js configuration
📄 tailwind.config.js ← Tailwind CSS setup
📄 .env.local ← Environment variables
📄 .gitignore ← Files to exclude from Git
📄 README.md ← Project documentation

The most important is next.config.js — where you customize Next.js behavior:

// next.config.js — NewsWave configuration
/** @type {import('next').NextConfig} */
const nextConfig = {
  // Enable image domains for external images
  images: {
    domains: ['images.unsplash.com', 'cdn.newswave.com']
  },
  
  // Experimental App Router features
  experimental: {
    appDir: true,
  },
  
  // Environment-specific settings
  env: {
    SITE_NAME: 'NewsWave',
    SITE_URL: 'https://newswave.com'
  }
}

module.exports = nextConfig

What just happened?

We configured Next.js to allow external images from Unsplash and our mock CDN. The experimental.appDir enables App Router features in older versions.

Try this: Add trailingSlash: true to force URLs to end with slashes.

Best Practices and Common Mistakes

After organizing hundreds of Next.js projects, here are the patterns that consistently work and the mistakes that consistently hurt:

✅ Do These

  • Keep components close to where they're used
  • Use descriptive folder names that match URLs
  • Start with flat structure, add nesting when needed
  • Keep lib/ for utilities, not components
  • Use private folders for internal organization

❌ Avoid These

  • Don't mix App Router and Pages Router in same project
  • Don't create routes without page.js files
  • Don't put user uploads in public/
  • Don't nest components more than 3 levels deep
  • Don't ignore TypeScript — it catches folder mistakes

Remember: your folder structure is your application's skeleton. It should make sense to someone seeing the code for the first time. If you're constantly confused about where to put files, your structure needs work.

Pro Tip: Start Simple

Begin with the default structure from create-next-app. Add folders only when you actually need them. Premature optimization applies to folder structure too — over-engineering organization slows you down more than having slightly messy folders.

Quiz

1. What happens when you create the folder structure app/category/tech/page.js in your NewsWave project?


2. In your NewsWave project, which folder pattern lets you organize files without creating URL routes?


3. Why does your NewsWave articles folder need a page.js file?


Up Next: Pages and Routing

Transform your folder structure into working pages and discover how Next.js automatically generates routes from your file system.