Next.js File Structure
Organize a Next.js project with the app folder, route groups, private folders, and colocated files.
TL;DR
- Put routes in the
appfolder and static files inpublic. - Group related routes with
(folder)names without changing any URL. - Hide helper folders from routing by prefixing them with
_.
Top-Level Folders
app/Holds every route, layout, and API endpoint in the App Router.
app/
layout.tsx
page.tsx
blog/
page.tsxpublic/Serves static files like images and icons from the root of the site.
public/
logo.svg # served at /logo.svg
og.png # served at /og.pngsrc/Optionally move app inside src to separate your code from config files.
src/
app/
components/
lib/
next.config.ts
package.jsonRoot Files
next.config.tsConfigure Next.js options such as images, redirects, and Turbopack in this file.
import type { NextConfig } from 'next';
const nextConfig: NextConfig = {};
export default nextConfig;proxy.tsRun code before a request completes; it replaces middleware.ts in Next.js 16.
// proxy.ts (project root, or inside src)
export function proxy(request: Request) {
// redirects, rewrites, headers
}.env.localKeep local secrets in this file and never commit it to git.
# .env.local (ignored by git)
DATABASE_URL="postgres://..."
# .env (shared defaults)
NEXT_PUBLIC_SITE_NAME="My App"Special Files in app
page.tsx and layout.tsxA page makes a route public, and a layout wraps that page and its children.
app/dashboard/
layout.tsx # shared shell
page.tsx # /dashboardloading.tsx and error.tsxShow a fallback while a route segment loads or after it throws an error.
app/dashboard/
loading.tsx # shown while loading
error.tsx # shown after an error
not-found.tsx # shown by notFound()route.tsCreate an API endpoint at the folder path by exporting HTTP method functions.
app/api/posts/
route.ts # /api/postsOrganizing Routes
(group)Wrap a folder name in parentheses to group routes without adding a URL segment.
app/
(marketing)/
about/page.tsx # /about
(shop)/
cart/page.tsx # /cart_folderPrefix a folder with an underscore to keep it out of routing entirely.
app/blog/
_components/
PostCard.tsx # never a route
page.tsxColocationKeep helper files beside the route that uses them; only page.tsx is public.
app/dashboard/
page.tsx
Chart.tsx # not routable
Chart.test.tsx@/ aliasImport from the project root with @/ instead of long relative paths.
import { Button } from '@/components/Button';
import { formatDate } from '@/lib/dates';Tips
- Keep components next to the route that uses them, and move a component to a shared
componentsfolder once two routes need it. - Use the
@/import alias fromcreate-next-appso files keep working when you move them between folders.
Warnings
- A folder cannot contain both
page.tsxandroute.ts, because one path cannot be a page and an endpoint. - Files in
publicare served to everyone, so never store secrets or private data in that folder.
In Practice
Give every shop page a shared navigation bar without changing any URL.
- The folder name (shop) groups routes but never appears in the URL.
- A layout inside the group wraps only the pages in that group.
- Pages outside the group, like the marketing pages, do not get this nav.
- The children prop is where each page in the group renders.
// app/(shop)/layout.tsx
import Link from 'next/link';
export default function ShopLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<div>
<nav>
<Link href="/products">Products</Link>
<Link href="/cart">Cart</Link>
</nav>
<main>{children}</main>
</div>
);
}FAQ
Next.js does not force one structure. A common setup keeps routes in app, shared UI in components, and helpers in lib. Pick one approach and use it everywhere in the project.
It is optional. A src folder separates your code from config files at the project root. If you use it, app and proxy.ts both move inside src.
Yes. Only page.tsx and route.ts files become public routes. Any other file in app is safe to keep there and is never served on its own.