Files
next.js/docs/01-app/01-getting-started/02-project-structure.mdx
Arian Tron 61f56f997c
Some checks failed
Test examples / Test Examples (20) (push) Has been cancelled
Test examples / Test Examples (22) (push) Has been cancelled
Lock Threads / action (push) Has been cancelled
Trigger Release / start (push) Has been cancelled
Stale issue handler / stale (push) Has been cancelled
Update Font Data / create-pull-request (push) Has been cancelled
build-and-deploy / deploy-target (push) Has been cancelled
build-and-deploy / build (push) Has been cancelled
build-and-deploy / stable - aarch64-unknown-linux-musl - node@16 (push) Has been cancelled
build-and-deploy / stable - x86_64-unknown-linux-musl - node@16 (push) Has been cancelled
build-and-deploy / stable - aarch64-unknown-linux-gnu - node@16 (push) Has been cancelled
build-and-deploy / stable - x86_64-unknown-linux-gnu - node@16 (push) Has been cancelled
build-and-deploy / stable - aarch64-pc-windows-msvc - node@16 (push) Has been cancelled
build-and-deploy / stable - x86_64-pc-windows-msvc - node@16 (push) Has been cancelled
build-and-deploy / stable - aarch64-apple-darwin - node@16 (push) Has been cancelled
build-and-deploy / stable - x86_64-apple-darwin - node@16 (push) Has been cancelled
build-and-deploy / build-wasm (nodejs) (push) Has been cancelled
build-and-deploy / build-wasm (web) (push) Has been cancelled
build-and-deploy / Deploy preview tarball (push) Has been cancelled
build-and-deploy / Potentially publish release (push) Has been cancelled
build-and-deploy / publish-turbopack-npm-packages (push) Has been cancelled
build-and-deploy / Deploy examples (push) Has been cancelled
build-and-deploy / thank you, build (push) Has been cancelled
build-and-deploy / Upload Turbopack Bytesize metrics to Datadog (push) Has been cancelled
Rspack Next.js development integration tests / Rspack integration tests (push) Has been cancelled
Rspack Next.js production integration tests / Rspack integration tests (push) Has been cancelled
Turbopack Next.js development integration tests / Next.js integration tests (push) Has been cancelled
Turbopack Next.js production integration tests / Next.js integration tests (push) Has been cancelled
Update Rspack test manifest / Update and upload Rspack development test manifest (push) Has been cancelled
Update Rspack test manifest / Update and upload Rspack production test manifest (push) Has been cancelled
Upload bundler test manifests to areweturboyet.com / Upload test results (push) Has been cancelled
Update React / create-pull-request (push) Has been cancelled
test-e2e-project-reset-cron / reset-test-project (push) Has been cancelled
Notify about the top 15 issues/PRs/feature requests (most reacted) in the last 90 days / run (push) Has been cancelled
first commit
2026-03-10 19:37:31 +03:30

422 lines
26 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: Project structure and organization
nav_title: Project Structure
description: Learn the folder and file conventions in Next.js, and how to organize your project.
---
This page provides an overview of **all** the folder and file conventions in Next.js, and recommendations for organizing your project.
## Folder and file conventions
### Top-level folders
Top-level folders are used to organize your application's code and static assets.
<Image
alt="Route segments to path segments"
srcLight="/docs/light/top-level-folders.png"
srcDark="/docs/dark/top-level-folders.png"
width="1600"
height="525"
/>
| | |
| ------------------------------------------------------------------ | ---------------------------------- |
| [`app`](/docs/app) | App Router |
| [`pages`](/docs/pages/building-your-application/routing) | Pages Router |
| [`public`](/docs/app/api-reference/file-conventions/public-folder) | Static assets to be served |
| [`src`](/docs/app/api-reference/file-conventions/src-folder) | Optional application source folder |
### Top-level files
Top-level files are used to configure your application, manage dependencies, run proxy, integrate monitoring tools, and define environment variables.
| | |
| ---------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- |
| **Next.js** | |
| [`next.config.js`](/docs/app/api-reference/config/next-config-js) | Configuration file for Next.js |
| [`package.json`](/docs/app/getting-started/installation#manual-installation) | Project dependencies and scripts |
| [`instrumentation.ts`](/docs/app/guides/instrumentation) | OpenTelemetry and Instrumentation file |
| [`proxy.ts`](/docs/app/api-reference/file-conventions/proxy) | Next.js request proxy |
| [`.env`](/docs/app/guides/environment-variables) | Environment variables (should not be tracked by version control) |
| [`.env.local`](/docs/app/guides/environment-variables) | Local environment variables (should not be tracked by version control) |
| [`.env.production`](/docs/app/guides/environment-variables) | Production environment variables (should not be tracked by version control) |
| [`.env.development`](/docs/app/guides/environment-variables) | Development environment variables (should not be tracked by version control) |
| [`eslint.config.mjs`](/docs/app/api-reference/config/eslint) | Configuration file for ESLint |
| `.gitignore` | Git files and folders to ignore |
| [`next-env.d.ts`](/docs/app/api-reference/config/typescript#next-envdts) | TypeScript declaration file for Next.js (should not be tracked by version control) |
| `tsconfig.json` | Configuration file for TypeScript |
| `jsconfig.json` | Configuration file for JavaScript |
<AppOnly>
### Routing Files
Add `page` to expose a route, `layout` for shared UI such as header, nav, or footer, `loading` for skeletons, `error` for error boundaries, and `route` for APIs.
| | | |
| ----------------------------------------------------------------------------- | ------------------- | ---------------------------- |
| [`layout`](/docs/app/api-reference/file-conventions/layout) | `.js` `.jsx` `.tsx` | Layout |
| [`page`](/docs/app/api-reference/file-conventions/page) | `.js` `.jsx` `.tsx` | Page |
| [`loading`](/docs/app/api-reference/file-conventions/loading) | `.js` `.jsx` `.tsx` | Loading UI |
| [`not-found`](/docs/app/api-reference/file-conventions/not-found) | `.js` `.jsx` `.tsx` | Not found UI |
| [`error`](/docs/app/api-reference/file-conventions/error) | `.js` `.jsx` `.tsx` | Error UI |
| [`global-error`](/docs/app/api-reference/file-conventions/error#global-error) | `.js` `.jsx` `.tsx` | Global error UI |
| [`route`](/docs/app/api-reference/file-conventions/route) | `.js` `.ts` | API endpoint |
| [`template`](/docs/app/api-reference/file-conventions/template) | `.js` `.jsx` `.tsx` | Re-rendered layout |
| [`default`](/docs/app/api-reference/file-conventions/default) | `.js` `.jsx` `.tsx` | Parallel route fallback page |
### Nested routes
Folders define URL segments. Nesting folders nests segments. Layouts at any level wrap their child segments. A route becomes public when a `page` or `route` file exists.
| Path | URL pattern | Notes |
| --------------------------- | --------------- | ----------------------------- |
| `app/layout.tsx` | — | Root layout wraps all routes |
| `app/blog/layout.tsx` | — | Wraps `/blog` and descendants |
| `app/page.tsx` | `/` | Public route |
| `app/blog/page.tsx` | `/blog` | Public route |
| `app/blog/authors/page.tsx` | `/blog/authors` | Public route |
### Dynamic routes
Parameterize segments with square brackets. Use `[segment]` for a single param, `[...segment]` for catchall, and `[[...segment]]` for optional catchall. Access values via the [`params`](/docs/app/api-reference/file-conventions/page#params-optional) prop.
| Path | URL pattern |
| ------------------------------- | -------------------------------------------------------------------- |
| `app/blog/[slug]/page.tsx` | `/blog/my-first-post` |
| `app/shop/[...slug]/page.tsx` | `/shop/clothing`, `/shop/clothing/shirts` |
| `app/docs/[[...slug]]/page.tsx` | `/docs`, `/docs/layouts-and-pages`, `/docs/api-reference/use-router` |
### Route groups and private folders
Organize code without changing URLs with route groups [`(group)`](/docs/app/api-reference/file-conventions/route-groups#convention), and colocate non-routable files with private folders [`_folder`](#private-folders).
| Path | URL pattern | Notes |
| ------------------------------- | ----------- | ----------------------------------------- |
| `app/(marketing)/page.tsx` | `/` | Group omitted from URL |
| `app/(shop)/cart/page.tsx` | `/cart` | Share layouts within `(shop)` |
| `app/blog/_components/Post.tsx` | — | Not routable; safe place for UI utilities |
| `app/blog/_lib/data.ts` | — | Not routable; safe place for utils |
### Parallel and Intercepted Routes
These features fit specific UI patterns, such as slot-based layouts or modal routing.
Use `@slot` for named slots rendered by a parent layout. Use intercept patterns to render another route inside the current layout without changing the URL, for example, to show a details view as a modal over a list.
| Pattern (docs) | Meaning | Typical use case |
| ------------------------------------------------------------------------------------------- | -------------------- | ---------------------------------------- |
| [`@folder`](/docs/app/api-reference/file-conventions/parallel-routes#slots) | Named slot | Sidebar + main content |
| [`(.)folder`](/docs/app/api-reference/file-conventions/intercepting-routes#convention) | Intercept same level | Preview sibling route in a modal |
| [`(..)folder`](/docs/app/api-reference/file-conventions/intercepting-routes#convention) | Intercept parent | Open a child of the parent as an overlay |
| [`(..)(..)folder`](/docs/app/api-reference/file-conventions/intercepting-routes#convention) | Intercept two levels | Deeply nested overlay |
| [`(...)folder`](/docs/app/api-reference/file-conventions/intercepting-routes#convention) | Intercept from root | Show arbitrary route in current view |
### Metadata file conventions
#### App icons
| | | |
| --------------------------------------------------------------------------------------------------------------- | ----------------------------------- | ------------------------ |
| [`favicon`](/docs/app/api-reference/file-conventions/metadata/app-icons#favicon) | `.ico` | Favicon file |
| [`icon`](/docs/app/api-reference/file-conventions/metadata/app-icons#icon) | `.ico` `.jpg` `.jpeg` `.png` `.svg` | App Icon file |
| [`icon`](/docs/app/api-reference/file-conventions/metadata/app-icons#generate-icons-using-code-js-ts-tsx) | `.js` `.ts` `.tsx` | Generated App Icon |
| [`apple-icon`](/docs/app/api-reference/file-conventions/metadata/app-icons#apple-icon) | `.jpg` `.jpeg`, `.png` | Apple App Icon file |
| [`apple-icon`](/docs/app/api-reference/file-conventions/metadata/app-icons#generate-icons-using-code-js-ts-tsx) | `.js` `.ts` `.tsx` | Generated Apple App Icon |
#### Open Graph and Twitter images
| | | |
| --------------------------------------------------------------------------------------------------------------------------- | ---------------------------- | -------------------------- |
| [`opengraph-image`](/docs/app/api-reference/file-conventions/metadata/opengraph-image#opengraph-image) | `.jpg` `.jpeg` `.png` `.gif` | Open Graph image file |
| [`opengraph-image`](/docs/app/api-reference/file-conventions/metadata/opengraph-image#generate-images-using-code-js-ts-tsx) | `.js` `.ts` `.tsx` | Generated Open Graph image |
| [`twitter-image`](/docs/app/api-reference/file-conventions/metadata/opengraph-image#twitter-image) | `.jpg` `.jpeg` `.png` `.gif` | Twitter image file |
| [`twitter-image`](/docs/app/api-reference/file-conventions/metadata/opengraph-image#generate-images-using-code-js-ts-tsx) | `.js` `.ts` `.tsx` | Generated Twitter image |
#### SEO
| | | |
| ------------------------------------------------------------------------------------------------------------ | ----------- | --------------------- |
| [`sitemap`](/docs/app/api-reference/file-conventions/metadata/sitemap#sitemap-files-xml) | `.xml` | Sitemap file |
| [`sitemap`](/docs/app/api-reference/file-conventions/metadata/sitemap#generating-a-sitemap-using-code-js-ts) | `.js` `.ts` | Generated Sitemap |
| [`robots`](/docs/app/api-reference/file-conventions/metadata/robots#static-robotstxt) | `.txt` | Robots file |
| [`robots`](/docs/app/api-reference/file-conventions/metadata/robots#generate-a-robots-file) | `.js` `.ts` | Generated Robots file |
</AppOnly>
<PagesOnly>
### File conventions
| | | |
| ----------------------------------------------------------------------------------------------------------- | ------------------- | ----------------- |
| [`_app`](/docs/pages/building-your-application/routing/custom-app) | `.js` `.jsx` `.tsx` | Custom App |
| [`_document`](/docs/pages/building-your-application/routing/custom-document) | `.js` `.jsx` `.tsx` | Custom Document |
| [`_error`](/docs/pages/building-your-application/routing/custom-error#more-advanced-error-page-customizing) | `.js` `.jsx` `.tsx` | Custom Error Page |
| [`404`](/docs/pages/building-your-application/routing/custom-error#404-page) | `.js` `.jsx` `.tsx` | 404 Error Page |
| [`500`](/docs/pages/building-your-application/routing/custom-error#500-page) | `.js` `.jsx` `.tsx` | 500 Error Page |
### Routes
| | | |
| ---------------------------------------------------------------------------------------------- | ------------------- | ----------- |
| **Folder convention** | | |
| [`index`](/docs/pages/building-your-application/routing/pages-and-layouts#index-routes) | `.js` `.jsx` `.tsx` | Home page |
| [`folder/index`](/docs/pages/building-your-application/routing/pages-and-layouts#index-routes) | `.js` `.jsx` `.tsx` | Nested page |
| **File convention** | | |
| [`index`](/docs/pages/building-your-application/routing/pages-and-layouts#index-routes) | `.js` `.jsx` `.tsx` | Home page |
| [`file`](/docs/pages/building-your-application/routing/pages-and-layouts) | `.js` `.jsx` `.tsx` | Nested page |
### Dynamic routes
| | | |
| ----------------------------------------------------------------------------------------------------------------- | ------------------- | -------------------------------- |
| **Folder convention** | | |
| [`[folder]/index`](/docs/pages/building-your-application/routing/dynamic-routes) | `.js` `.jsx` `.tsx` | Dynamic route segment |
| [`[...folder]/index`](/docs/pages/building-your-application/routing/dynamic-routes#catch-all-segments) | `.js` `.jsx` `.tsx` | Catch-all route segment |
| [`[[...folder]]/index`](/docs/pages/building-your-application/routing/dynamic-routes#optional-catch-all-segments) | `.js` `.jsx` `.tsx` | Optional catch-all route segment |
| **File convention** | | |
| [`[file]`](/docs/pages/building-your-application/routing/dynamic-routes) | `.js` `.jsx` `.tsx` | Dynamic route segment |
| [`[...file]`](/docs/pages/building-your-application/routing/dynamic-routes#catch-all-segments) | `.js` `.jsx` `.tsx` | Catch-all route segment |
| [`[[...file]]`](/docs/pages/building-your-application/routing/dynamic-routes#optional-catch-all-segments) | `.js` `.jsx` `.tsx` | Optional catch-all route segment |
</PagesOnly>
<AppOnly>
## Organizing your project
Next.js is **unopinionated** about how you organize and colocate your project files. But it does provide several features to help you organize your project.
### Component hierarchy
The components defined in special files are rendered in a specific hierarchy:
- `layout.js`
- `template.js`
- `error.js` (React error boundary)
- `loading.js` (React suspense boundary)
- `not-found.js` (React error boundary for "not found" UI)
- `page.js` or nested `layout.js`
<Image
alt="Component Hierarchy for File Conventions"
srcLight="/docs/light/file-conventions-component-hierarchy.png"
srcDark="/docs/dark/file-conventions-component-hierarchy.png"
width="1600"
height="643"
/>
The components are rendered recursively in nested routes, meaning the components of a route segment will be nested **inside** the components of its parent segment.
<Image
alt="Nested File Conventions Component Hierarchy"
srcLight="/docs/light/nested-file-conventions-component-hierarchy.png"
srcDark="/docs/dark/nested-file-conventions-component-hierarchy.png"
width="1600"
height="863"
/>
### Colocation
In the `app` directory, nested folders define route structure. Each folder represents a route segment that is mapped to a corresponding segment in a URL path.
However, even though route structure is defined through folders, a route is **not publicly accessible** until a `page.js` or `route.js` file is added to a route segment.
<Image
alt="A diagram showing how a route is not publicly accessible until a page.js or route.js file is added to a route segment."
srcLight="/docs/light/project-organization-not-routable.png"
srcDark="/docs/dark/project-organization-not-routable.png"
width="1600"
height="444"
/>
And, even when a route is made publicly accessible, only the **content returned** by `page.js` or `route.js` is sent to the client.
<Image
alt="A diagram showing how page.js and route.js files make routes publicly accessible."
srcLight="/docs/light/project-organization-routable.png"
srcDark="/docs/dark/project-organization-routable.png"
width="1600"
height="687"
/>
This means that **project files** can be **safely colocated** inside route segments in the `app` directory without accidentally being routable.
<Image
alt="A diagram showing colocated project files are not routable even when a segment contains a page.js or route.js file."
srcLight="/docs/light/project-organization-colocation.png"
srcDark="/docs/dark/project-organization-colocation.png"
width="1600"
height="1011"
/>
> **Good to know**: While you **can** colocate your project files in `app` you don't **have** to. If you prefer, you can [keep them outside the `app` directory](#store-project-files-outside-of-app).
### Private folders
Private folders can be created by prefixing a folder with an underscore: `_folderName`
This indicates the folder is a private implementation detail and should not be considered by the routing system, thereby **opting the folder and all its subfolders** out of routing.
<Image
alt="An example folder structure using private folders"
srcLight="/docs/light/project-organization-private-folders.png"
srcDark="/docs/dark/project-organization-private-folders.png"
width="1600"
height="849"
/>
Since files in the `app` directory can be [safely colocated by default](#colocation), private folders are not required for colocation. However, they can be useful for:
- Separating UI logic from routing logic.
- Consistently organizing internal files across a project and the Next.js ecosystem.
- Sorting and grouping files in code editors.
- Avoiding potential naming conflicts with future Next.js file conventions.
> **Good to know**:
>
> - While not a framework convention, you might also consider marking files outside private folders as "private" using the same underscore pattern.
> - You can create URL segments that start with an underscore by prefixing the folder name with `%5F` (the URL-encoded form of an underscore): `%5FfolderName`.
> - If you don't use private folders, it would be helpful to know Next.js [special file conventions](/docs/app/getting-started/project-structure#routing-files) to prevent unexpected naming conflicts.
### Route groups
Route groups can be created by wrapping a folder in parenthesis: `(folderName)`
This indicates the folder is for organizational purposes and should **not be included** in the route's URL path.
<Image
alt="An example folder structure using route groups"
srcLight="/docs/light/project-organization-route-groups.png"
srcDark="/docs/dark/project-organization-route-groups.png"
width="1600"
height="849"
/>
Route groups are useful for:
- Organizing routes by site section, intent, or team. e.g. marketing pages, admin pages, etc.
- Enabling nested layouts in the same route segment level:
- [Creating multiple nested layouts in the same segment, including multiple root layouts](#creating-multiple-root-layouts)
- [Adding a layout to a subset of routes in a common segment](#opting-specific-segments-into-a-layout)
### `src` folder
Next.js supports storing application code (including `app`) inside an optional [`src` folder](/docs/app/api-reference/file-conventions/src-folder). This separates application code from project configuration files which mostly live in the root of a project.
<Image
alt="An example folder structure with the `src` folder"
srcLight="/docs/light/project-organization-src-directory.png"
srcDark="/docs/dark/project-organization-src-directory.png"
width="1600"
height="687"
/>
## Examples
The following section lists a very high-level overview of common strategies. The simplest takeaway is to choose a strategy that works for you and your team and be consistent across the project.
> **Good to know**: In our examples below, we're using `components` and `lib` folders as generalized placeholders, their naming has no special framework significance and your projects might use other folders like `ui`, `utils`, `hooks`, `styles`, etc.
### Store project files outside of `app`
This strategy stores all application code in shared folders in the **root of your project** and keeps the `app` directory purely for routing purposes.
<Image
alt="An example folder structure with project files outside of app"
srcLight="/docs/light/project-organization-project-root.png"
srcDark="/docs/dark/project-organization-project-root.png"
width="1600"
height="849"
/>
### Store project files in top-level folders inside of `app`
This strategy stores all application code in shared folders in the **root of the `app` directory**.
<Image
alt="An example folder structure with project files inside app"
srcLight="/docs/light/project-organization-app-root.png"
srcDark="/docs/dark/project-organization-app-root.png"
width="1600"
height="849"
/>
### Split project files by feature or route
This strategy stores globally shared application code in the root `app` directory and **splits** more specific application code into the route segments that use them.
<Image
alt="An example folder structure with project files split by feature or route"
srcLight="/docs/light/project-organization-app-root-split.png"
srcDark="/docs/dark/project-organization-app-root-split.png"
width="1600"
height="1011"
/>
### Organize routes without affecting the URL path
To organize routes without affecting the URL, create a group to keep related routes together. The folders in parenthesis will be omitted from the URL (e.g. `(marketing)` or `(shop)`).
<Image
alt="Organizing Routes with Route Groups"
srcLight="/docs/light/route-group-organisation.png"
srcDark="/docs/dark/route-group-organisation.png"
width="1600"
height="930"
/>
Even though routes inside `(marketing)` and `(shop)` share the same URL hierarchy, you can create a different layout for each group by adding a `layout.js` file inside their folders.
<Image
alt="Route Groups with Multiple Layouts"
srcLight="/docs/light/route-group-multiple-layouts.png"
srcDark="/docs/dark/route-group-multiple-layouts.png"
width="1600"
height="768"
/>
### Opting specific segments into a layout
To opt specific routes into a layout, create a new route group (e.g. `(shop)`) and move the routes that share the same layout into the group (e.g. `account` and `cart`). The routes outside of the group will not share the layout (e.g. `checkout`).
<Image
alt="Route Groups with Opt-in Layouts"
srcLight="/docs/light/route-group-opt-in-layouts.png"
srcDark="/docs/dark/route-group-opt-in-layouts.png"
width="1600"
height="930"
/>
### Opting for loading skeletons on a specific route
To apply a [loading skeleton](/docs/app/api-reference/file-conventions/loading) via a `loading.js` file to a specific route, create a new route group (e.g., `/(overview)`) and then move your `loading.tsx` inside that route group.
<Image
alt="Folder structure showing a loading.tsx and a page.tsx inside the route group"
srcLight="/docs/light/route-group-loading.png"
srcDark="/docs/dark/route-group-loading.png"
width="1600"
height="444"
/>
Now, the `loading.tsx` file will only apply to your dashboard → overview page instead of all your dashboard pages without affecting the URL path structure.
### Creating multiple root layouts
To create multiple [root layouts](/docs/app/api-reference/file-conventions/layout#root-layout), remove the top-level `layout.js` file, and add a `layout.js` file inside each route group. This is useful for partitioning an application into sections that have a completely different UI or experience. The `<html>` and `<body>` tags need to be added to each root layout.
<Image
alt="Route Groups with Multiple Root Layouts"
srcLight="/docs/light/route-group-multiple-root-layouts.png"
srcDark="/docs/dark/route-group-multiple-root-layouts.png"
width="1600"
height="687"
/>
In the example above, both `(marketing)` and `(shop)` have their own root layout.
</AppOnly>