Chapter 3: Understanding Next.js Project Structure
What is the Next.js Project Structure?
The Next.js project structure is a well-organized file system that follows conventions to automatically handle routing, styling, and application configuration. Understanding this structure is crucial for building maintainable and scalable Next.js applications.
Core Principles:
- Convention over Configuration: File placement determines functionality
- File-based Routing: Each file in
pages/
becomes a route - Separation of Concerns: Clear separation between pages, components, and assets
- Scalability: Structure supports both small and large applications
Why This Structure Matters
Benefits:
- Predictable Organization: Developers know where to find and place files
- Automatic Routing: No manual route configuration needed
- Build Optimization: Next.js can optimize based on file structure
- Team Collaboration: Consistent structure improves team productivity
- Easy Maintenance: Clear separation makes debugging and updates easier
How the Structure Works
Standard Next.js Structure
my-nextjs-app/
├── .next/ # Build output (auto-generated)
├── .gitignore # Git ignore rules
├ ── node_modules/ # Dependencies
├── pages/ # File-based routing
│ ├── api/ # API routes
│ │ └── hello.js # /api/hello endpoint
│ ├── _app.js # Custom App component
│ ├── _document.js # Custom Document component
│ ├── index.js # Home page (/)
│ ├── about.js # About page (/about)
│ └── blog/
│ ├── index.js # Blog listing (/blog)
│ └── [slug].js # Dynamic blog post (/blog/[slug])
├── public/ # Static assets
│ ├── favicon.ico
│ ├── images/
│ └── icons/
├── styles/ # CSS files
│ ├── globals.css # Global styles
│ └── Home.module.css # Component-specific styles
├── components/ # Reusable components
│ ├── Layout.js
│ ├── Header.js
│ └── Footer.js
├── lib/ # Utility functions
│ └── utils.js
├── package.json
├── next.config.js # Next.js configuration
└── README.md
Detailed Directory Breakdown
1. Pages Directory (pages/
)
The pages/
directory is the heart of Next.js routing:
// pages/index.js - Home page (/)
export default function Home() {
return <h1>Welcome to Next.js!</h1>
}
// pages/about.js - About page (/about)
export default function About() {
return <h1>About Us</h1>
}
// pages/blog/index.js - Blog listing (/blog)
export default function Blog() {
return <h1>Blog Posts</h1>
}
// pages/blog/[slug].js - Dynamic blog post (/blog/hello-world)
import { useRouter } from 'next/router'
export default function BlogPost() {
const router = useRouter()
const { slug } = router.query
return <h1>Blog Post: {slug}</h1>
}
2. API Routes (pages/api/
)
API routes create serverless functions:
// pages/api/hello.js
export default function handler(req, res) {
res.status(200).json({ message: 'Hello from Next.js API!' })
}
// pages/api/users/[id].js
export default function handler(req, res) {
const { id } = req.query
res.status(200).json({ userId: id })
}
3. Public Directory (public/
)
Static assets served directly:
public/
├── favicon.ico # Site icon
├── images/
│ ├── logo.png
│ └── hero.jpg
├── icons/
│ ├── icon-192.png
│ └── icon-512.png
└── manifest.json # PWA manifest
4. Components Directory (components/
)
Reusable React components:
// components/Layout.js
import Header from './Header'
import Footer from './Footer'
export default function Layout({ children }) {
return (
<div>
<Header />
<main>{children}</main>
<Footer />
</div>
)
}
// components/Header.js
export default function Header() {
return (
<header>
<nav>
<a href="/">Home</a>
<a href="/about">About</a>
</nav>
</header>
)
}
5. Styles Directory (styles/
)
CSS and styling files:
/* styles/globals.css */
html,
body {
padding: 0;
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
}
a {
color: inherit;
text-decoration: none;
}
* {
box-sizing: border-box;
}
/* styles/Home.module.css */
.container {
padding: 0 2rem;
}
.main {
min-height: 100vh;
padding: 4rem 0;
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
Special Files Explained
1. _app.js
- Custom App Component
// pages/_app.js
import '../styles/globals.css'
export default function MyApp({ Component, pageProps }) {
return <Component {...pageProps} />
}
Purpose:
- Wraps all pages
- Shared layout and state
- Global CSS imports
- Error handling
2. _document.js
- Custom Document
// pages/_document.js
import { Html, Head, Main, NextScript } from 'next/document'
export default function Document() {
return (
<Html lang="en">
<Head>
<meta name="description" content="My Next.js app" />
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
Purpose:
- Custom HTML document structure
- Global meta tags
- Custom fonts and scripts
- Server-side rendering customization
3. next.config.js
- Configuration
// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
swcMinify: true,
images: {
domains: ['example.com'],
},
async rewrites() {
return [
{
source: '/api/:path*',
destination: 'https://api.example.com/:path*',
},
]
},
}
module.exports = nextConfig
Advanced Structure Patterns
1. Feature-Based Organization
src/
├── components/
│ ├── ui/ # Reusable UI components
│ ├── forms/ # Form components
│ └── layout/ # Layout components
├── pages/
├── hooks/ # Custom React hooks
├── utils/ # Utility functions
├── services/ # API services
├── types/ # TypeScript types
└── constants/ # Application constants
2. Monorepo Structure
apps/
├── web/ # Next.js web app
├── admin/ # Admin dashboard
└── mobile/ # React Native app
packages/
├── ui/ # Shared UI components
├── utils/ # Shared utilities
└── types/ # Shared TypeScript types
Best Practices
1. File Naming Conventions
// ✅ Good: PascalCase for components
components/UserProfile.js
components/ProductCard.js
// ✅ Good: camelCase for utilities
utils/formatDate.js
utils/apiClient.js
// ✅ Good: kebab-case for pages (optional)
pages/user-profile.js
pages/product-details.js
2. Import Organization
// ✅ Good: Organized imports
import React from 'react'
import { useRouter } from 'next/router'
import Layout from '../components/Layout'
import { formatDate } from '../utils/dateUtils'
import styles from './Home.module.css'
3. Component Structure
// ✅ Good: Well-structured component
import React, { useState, useEffect } from 'react'
import PropTypes from 'prop-types'
import styles from './Component.module.css'
export default function Component({ title, data }) {
const [state, setState] = useState(null)
useEffect(() => {
// Side effects
}, [])
return (
<div className={styles.container}>
<h1>{title}</h1>
{/* Component content */}
</div>
)
}
Component.propTypes = {
title: PropTypes.string.isRequired,
data: PropTypes.array,
}
Common Mistakes to Avoid
1. Incorrect File Placement
// ❌ Wrong: Component in pages directory
pages/Header.js // This creates a route!
// ✅ Correct: Component in components directory
components/Header.js
2. Missing Special Files
// ❌ Wrong: No _app.js for global styles
// Global styles won't be applied
// ✅ Correct: Import in _app.js
// pages/_app.js
import '../styles/globals.css'
3. Inefficient Imports
// ❌ Wrong: Importing entire library
import * as _ from 'lodash'
// ✅ Correct: Import specific functions
import { debounce } from 'lodash'
Summary
Understanding the Next.js project structure is fundamental to building successful applications. The structure provides:
- Automatic routing through file placement
- Clear separation of concerns
- Scalable organization for growing applications
- Convention-based development approach
Key Takeaways:
- The
pages/
directory controls routing _app.js
wraps all pages_document.js
customizes HTML structurepublic/
serves static assets- Components should be in
components/
directory - Follow naming conventions for consistency
This tutorial is part of the comprehensive Next.js learning path at syscook.dev. Continue to the next chapter to learn about routing and navigation.
Author: syscook.dev
Last Updated: December 2024