October 19, 2024
O. Wolfson
With the release of Next.js 14 and the continued refinement of the App Router, the framework provides more robust conventions for project organization, specifically focusing on file colocation. File colocation is a key pattern that Next.js developers can leverage to streamline their code structure, making it easier to maintain and scale applications.
This article explores best practices for organizing your Next.js 14+ project, particularly focusing on file colocation with the App Router.
File colocation refers to the practice of keeping related files close together within the directory structure. In a Next.js project, this means grouping together components, styles, tests, and sometimes even data-fetching logic within the same directory as the page or component that uses them. The goal is to create a more modular, understandable structure, reducing the need to jump between distant files.
Next.js 14+ and the App Router enhance file colocation by allowing you to place files directly alongside their related routes, simplifying the organization and allowing for easy discovery of relevant code.
The App Router in Next.js 14 introduces a new way to structure your application, where the app/
directory becomes the central point for all routing. Here's a general example of a project structure:
bashmy-nextjs-app/ │ ├── app/ │ ├── actions/ │ ├── (auth)/ │ │ ├── login/ │ │ │ ├── page.tsx │ │ │ └── login.module.css │ ├── dashboard/ │ │ ├── page.tsx │ │ ├── component.tsx │ │ ├── component.test.tsx │ │ └── dashboard.module.css │ └── layout.tsx │ ├── components/ │ └── Header.tsx │ ├── public/ │ └── images/ ├── utils/ └── styles/
This structure illustrates how colocation works with the App Router:
Pages and Routes: The app/
directory handles routing based on its folder structure. For example, the app/(auth)/login/page.tsx
file automatically becomes the route for /login
.
Colocation of Components, Styles, and Tests: Notice that components like component.tsx
, styles like dashboard.module.css
, and tests like component.test.tsx
are colocated within the dashboard/
route. This keeps all the relevant code close to the page where it's used.
Layout Files: The layout.tsx
file in the app/
directory defines shared layouts for your app, colocating layout code close to the routes it affects.
Enhanced Discoverability: When you colocate files, it becomes easier to locate the code that belongs to a specific page or feature. If you're working on the /dashboard
page, all the related files (components, styles, tests, etc.) are stored in the same directory.
Modular Organization: By grouping related files together, you create self-contained modules. This can improve reusability, as each module is self-sufficient, with all dependencies local to that directory.
Simplified Maintenance: Colocated files reduce the cognitive overhead of managing large applications. When you need to make changes to a feature or fix bugs, you don't have to navigate between distant directories.
Logical Grouping: With Next.js 14+, your application’s structure reflects the actual routing and user experience. The routes in the app/
directory closely mirror the application’s URL structure, making it easier for new developers to understand the flow of the app.
In Next.js 14+, the App Router treats any page.tsx
file as a route handler, and you can colocate other files like components and styles next to it. Additionally, layout files, such as layout.tsx
, can be used to define reusable layouts for nested routes.
For example:
bashapp/
├── dashboard/
│ ├── page.tsx # This is the /dashboard page
│ ├── layout.tsx # Optional layout for the dashboard section
│ ├── component.tsx # A specific component used only in the dashboard
│ └── dashboard.module.css # CSS specific to the dashboard page
This colocates everything related to the dashboard/
page in one folder, minimizing separation between related logic.
In Next.js 14+, Server Actions can be colocated as well. These actions, which handle server-side functionality (such as form submissions or database interactions), can be placed directly in a actions/
directory under app/
.
Example:
bashapp/
├── dashboard/
│ ├── actions/
│ │ └── submitAction.ts # Handles form submission for dashboard
│ ├── page.tsx
By colocating actions with the route that uses them, you ensure server-side logic is tightly coupled with the front-end UI code.
File colocation is also compatible with dynamic routes. If your app uses dynamic segments in its URLs (e.g., /users/[id]
), you can colocate logic for specific dynamic pages:
bashapp/
├── users/
│ ├── [id]/
│ │ ├── page.tsx # Handles /users/:id
│ │ └── user.module.css # Styles specific to the user page
This structure keeps the logic for dynamic routes in a logical, organized structure.
While colocation is an excellent practice for most use cases, there are times when it may not be the best fit. Here’s a quick guide:
Use Colocation:
Avoid Colocation:
components/
or utils/
to avoid duplication.styles/
directory.app/
directory.In Next.js 14+, file colocation is not only encouraged but is also a natural fit with the App Router. By grouping files together based on their functionality and proximity to routes, you can maintain a clean, modular structure that scales well as your application grows. Colocation makes code easier to discover, enhances modularity, and simplifies maintenance, helping to make your Next.js project more organized and efficient.