Get in touch
or send us a question?
CONTACT

Next.js Folder Structure Simplified: A Comprehensive Overview

Next.js has rapidly become a cornerstone of the React ecosystem, offering developers a robust framework for building server-side rendering and static web applications. Its popularity is due in part to its ease of use, performance implications, and the seamless development experience it provides.

As you create a Next.js app, understanding the Next.js folder structure is crucial. This structure is the backbone of your app, influencing everything from routing to data fetching.

The app router in Next.js 13 introduces a new way to handle routing and error handling, leveraging updates made in the latest version of React.

A well-organized folder structure ensures that your application code remains maintainable and scalable as your app grows. It can also have performance implications, as a clear separation of server components and client components allows for more efficient server-side rendering and client-side execution. Moreover, a logical folder structure is essential for team collaboration, as it helps developers navigate the project and understand the app’s architecture at a glance.

Getting Started with Next.js

Creating a New Next.js Project

Embarking on a new Next.js project is an exciting venture. To get started, you’ll need to have Node.js installed on your system. With Node.js ready, you can create your next app using the following command in your terminal. This command scaffolds a new Next.js project with the latest version of Next.js, setting up all the necessary files and folders to jumpstart your development.

1npx create-next-app@latest project-name

Replace project-name with the desired project name. This command will create a new directory with your project name and install all of the requirements needed to run a Next.js app.

Initial Files and Directories

Once the installation is complete, you’ll find that Next.js has generated a default directory structure for you. This initial file structure is designed to give you a head start with a functional app right out of the box. Here’s what you can expect:

  • pages directory: This folder is the heart of your Next.js app’s routing system. Each .js file or .tsx file inside this directory automatically becomes a route based on its file name.
  • public folder: This is where you’ll place static assets like images, fonts, and any other files that need to be accessed publicly.
  • styles folder: Contains the default CSS files for styling your app. You can add your own stylesheets here or modify the existing ones to tailor the look and feel of your app.
  • .next folder: This is a generated folder that contains the output of the Next.js build process. You typically won’t need to touch this folder directly.
  • node_modules directory: Houses all the third-party libraries and dependencies for your app.
  • package.json file: This json file keeps track of all the dependencies and scripts for your Next.js project. It’s an essential part of your app’s configuration.
  • next.config.js file: Optional config file that allows you to customize various aspects of Next.js behavior.
  • .gitignore file: A pre-configured file that tells Git which files or folders to ignore in your project.
  • README.md file: A markdown file where you can provide information about your project, such as setup instructions and documentation.

Default Folder Structure of Next.js

The pages Directory

At the core of every Next.js app is the pages directory. This folder is where the magic of file-based routing takes place. Each .js or .tsx file within this directory corresponds to a route in your app, with the file name dictating the route’s URL path. React Server Components improve performance and user experience by optimizing bundle size and providing fine-grained control over data-fetching.

The pages directory also plays a crucial role in the overall architecture of the app. A server component acts as a special layout that manipulates the HTML returned by the server and persists data or state throughout the app’s lifecycle.

The Significance of index.js

The index.js file within the pages directory holds a place of honor as it represents the entry point of your Next.js app, or the home page. When users visit the root of your app, this is the file that gets rendered.

File System for Routing

Next.js uses the file system to map files in the pages directory to the routing system. For example, a file named about.js would automatically be accessible at the /about route. This convention provides a straightforward and intuitive approach to creating new routes.

The public Directory

The public folder is where all your static assets reside. Images, icons, fonts, and any other files that need to be served as-is can be placed here. These files are accessible from the root URL, which means an image at public/images/logo.png can be accessed via /images/logo.png in your app.

The styles Directory

Next.js also sets up a styles directory for you to jumpstart the process of styling your app. It includes a default CSS file that applies some basic styles to start with. You can add more CSS or SASS files here to customize your app’s design. Next.js supports CSS Modules out of the box, allowing for component-scoped styles, which is a common pattern for styling in the React ecosystem.

1/* styles/Home.module.css */ 2.container { 3 padding: 50px; 4 text-align: center; 5}

In this CSS snippet, we define some styles for a container class that could be used in the index.js file of the pages directory to style the home page. The modular approach to styling helps in maintaining a clean and organized stylesheet structure.

Customizable Folders and Files

While Next.js provides a default folder structure, it also allows for customization to suit your project’s needs. Here are some common customizable folders and files that developers often add to their Next.js projects:

The components Directory

The components directory, although not created by default, is a widely adopted convention in Next.js projects. This directory is where you can organize your reusable React components, which helps in keeping your application code DRY (Don’t Repeat Yourself). By storing different components such as buttons, headers, and footers in the components folder, you can easily import and use them across various parts of your app.

The lib or utils Directory

For utility functions and libraries that are used throughout your app, a lib (short for “library”) or utils (short for “utilities”) directory can be very helpful. This could include functions for data fetching, formatting dates, or any other logic that you want to abstract away and use in multiple places within your app.

The hooks Directory

Custom React hooks allow you to extract component logic into reusable functions. A hooks directory is a great place to keep these custom hooks organized. While optional, having a dedicated folder for hooks can make them easier to find and manage as your app grows.

The models or schemas Directory

If your app involves working with data models or schemas (for example, when using a database), you might choose to add a models or schemas directory. This folder would contain definitions for the structure of your data, such as the fields and data types for database entries.

These customizable directories are not mandatory, but they are a common pattern in the Next.js community. They help keep your project organized and your codebase clean, especially as your app scales and becomes more complex.

Special Files in Next.js

Next.js includes several special files that play key roles in configuring and managing your app. Understanding these files is essential for customizing your Next.js project and ensuring it runs smoothly.

next.config.js

The next.config.js file is where you can specify custom configuration options for your Next.js app. This file is not created by default, but you can create it at the root of your project if you need to customize settings like build output, modify webpack configurations, add environment variables, or implement redirects and rewrites.

1// next.config.js 2module.exports = { 3 reactStrictMode: true, 4 // Add custom config options here 5};

In this example, reactStrictMode is set to true, which enables strict mode for all React components in your application.

.env.local and Environment Variables

Environment variables are used to store sensitive information that you don’t want to include in your version control system, such as API keys or database passwords. In Next.js, you can create a .env.local file at the root of your project to define these variables. Next.js will load these variables at build time, making them available in your app through process.env.

1# .env.local 2API_SECRET=your_secret_key 3DATABASE_URL=your_database_url

These variables can then be accessed in your Next.js app using process.env.API_SECRET and process.env.DATABASE_URL.

package.json

The package.json file is a fundamental part of any Node.js or JavaScript project, including Next.js apps. It keeps track of all the dependencies your project needs to run, as well as scripts for executing common tasks like building, developing, and testing your app.

1{ 2 "name": "my-nextjs-app", 3 "version": "1.0.0", 4 "scripts": { 5 "dev": "next dev", 6 "build": "next build", 7 "start": "next start" 8 }, 9 "dependencies": { 10 "next": "^10.0.0", 11 "react": "^17.0.0", 12 "react-dom": "^17.0.0" 13 } 14}

In this package.json snippet, you can see the scripts section with commands to start the development server, build the app, and run the production server. The dependencies section lists the Next.js framework and React libraries required for the app to function.

These special files are integral to the operation and customization of your Next.js project, giving you control over its behavior and environment.

API Routes in Next.js

The pages/api Directory

Next.js offers a seamless way to create API endpoints within your app using the pages/api directory. This directory is specially treated by Next.js to define serverless functions that handle HTTP requests. Each file inside this directory corresponds to an API route and exports request handler functions.

Structuring API Endpoints

To structure your API endpoints, simply create .js or .tsx files within the pages/api directory. The file path relative to this directory determines the API route’s URL path. For example, a file named users.js at pages/api/users.js would create an endpoint accessible at /api/users.

Serverless Functions in Next.js

The functions you define in the pages/api directory are serverless functions, meaning they run on demand in response to HTTP requests. This serverless approach allows for efficient scaling and is a cost-effective solution for handling backend logic.

1// pages/api/greet.js 2export default function handler(req, res) { 3 res.status(200).json({ message: 'Hello, Next.js!' }); 4}

In this example, we have a simple API route handler in pages/api/greet.js that responds with a JSON object containing a greeting message. This function will be invoked when a request is made to the /api/greet endpoint.

SEO and Performance Optimization

Next.js Sitemap

sitemap is an XML file that lists the URLs for a site, which is crucial for SEO as it helps search engines discover and index the site’s content. In Next.js, you can generate a sitemap programmatically using the getServerSideProps or getStaticProps functions to fetch all the routes in your application and then output them to an XML file. This file can be served statically from the public directory or generated on the fly for dynamic content.

Advanced Folder Structure Concepts

As your Next.js app grows in complexity, you may need to implement more advanced folder structure concepts to keep your project organized and maintainable. Here are some of the advanced concepts you can use:

Nested Routes and Dynamic Routing

Next.js supports nested routes and dynamic routing, allowing you to create complex routing patterns that reflect your app’s structure. Nested routes are achieved by creating a folder within the pages directory that corresponds to a subpath in the URL. For dynamic routing, you can use bracket syntax ([param]) to create dynamic route segments.

Route groups can be created by wrapping folder names in parentheses. This helps organize files into groups without affecting the route’s URL path. For example, you can create a directory named (admin) and place your admin-related pages inside it. The URL path will not include the (admin) folder name, keeping the routes clean and organized.

1// pages/posts/[id].js 2import React from 'react'; 3 4const Post = ({ id }) => { 5 return <div>Post ID: {id}</div>; 6}; 7 8Post.getInitialProps = async ({ query }) => { 9 return { id: query.id }; 10}; 11 12export default Post;

In this example, the file is named [id].js within the posts folder, creating a dynamic route that matches any /posts/some-id pattern, where some-id is the dynamic part of the URL. The route’s URL path is determined by the file structure, and route groups can be used to manage complex routing patterns effectively.

The layouts Directory for Page Layouts (Optional)

layouts directory can be used to store layout components that wrap around your page content. This is useful for maintaining consistent layouts across different parts of your app, such as headers, footers, and sidebars.

1// components/layouts/MainLayout.js 2import React from 'react'; 3 4const MainLayout = ({ children }) => { 5 return ( 6 <div> 7 <header>Header Content</header> 8 <main>{children}</main> 9 <footer>Footer Content</footer> 10 </div> 11 ); 12}; 13 14export default MainLayout;

In this layout file, you can wrap your page content with a common header and footer, ensuring a consistent look and feel across your app.

The middleware Directory for Custom Middleware (Optional)

Custom middleware in Next.js allows you to execute code before a request is completed. By creating a middleware directory, you can organize your middleware functions that can run on the server side, client side, or both.

1// middleware/auth.js 2export function checkAuth(req, res, next) { 3 // Authentication logic here 4 next(); 5}

This middleware function can be used to check authentication before a page or API route is served.