Next.js 16 File Conventions — The Complete Reference

Step 31 of 31Next.js Tutorial Series | Source code

Live Demo →


What You Will Learn

↑ Index

  • Every special file name recognized by the Next.js 16 App Router
  • Which files are route-level, app-wide, or project-root conventions
  • What changed from earlier Next.js versions (deprecated and renamed files)
  • A practical quick-reference table you can bookmark

Table of Contents

  1. How File Conventions Work
  2. Route UI Files
  3. Error & Loading Files
  4. Not Found Handling
  5. API Routes
  6. Dynamic Route Segments
  7. Route Groups & Parallel Routes
  8. Intercepting Routes
  9. Proxy (formerly Middleware)
  10. Static Metadata Files
  11. Project Config Files
  12. Deprecated Conventions
  13. What You Actually Need
  14. Summary & Key Takeaways

How File Conventions Work

↑ Index

Next.js 16 uses the App Router. When you create a file with a specific name inside the app/ directory, Next.js automatically assigns it special behavior — no configuration required.

These conventions fall into three categories:

CategoryExamples
Route-levelpage.tsx, layout.tsx, loading.tsx, error.tsx, not-found.tsx
App-wide / Rootapp/layout.tsx (root layout), app/not-found.tsx (global 404)
Project rootproxy.ts, instrumentation.ts, next.config.ts

All examples use .tsx / .ts, but .jsx / .js work identically.


Route UI Files

↑ Index

page.tsx

Defines the UI for a route. A folder only becomes a publicly accessible route when it contains a page.tsx.

// app/posts/page.tsx → accessible at /posts
export default function PostsPage() {
  return <h1>Posts</h1>
}

layout.tsx

Shared UI that wraps child routes. Layouts persist across navigations — they don't remount.

// app/dashboard/layout.tsx
export default function DashboardLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <div>
      <nav>Dashboard Nav</nav>
      {children}
    </div>
  )
}

The root layout (app/layout.tsx) is required and must include <html> and <body> tags.

template.tsx

Like layout.tsx but re-renders on every navigation. Use it when you need a fresh component instance each time (e.g. enter/exit animations, resetting state).

// app/dashboard/template.tsx
export default function Template({ children }: { children: React.ReactNode }) {
  return <div>{children}</div>
}

default.tsx

Fallback UI for parallel routes when Next.js can't determine which slot to render after a navigation.

// app/@analytics/default.tsx
export default function Default() {
  return null
}

Error & Loading Files

↑ Index

error.tsx

Catches runtime errors inside a route segment. Must be a Client Component.

// app/posts/error.tsx
'use client'

export default function Error({
  error,
  reset,
}: {
  error: Error
  reset: () => void
}) {
  return (
    <div>
      <p>Something went wrong: {error.message}</p>
      <button onClick={reset}>Try again</button>
    </div>
  )
}

global-error.tsx

Catches errors in the root layout itself. Also must be a Client Component. Must render its own <html> and <body>.

loading.tsx

Displayed automatically while the route's page.tsx is loading. Next.js wraps the page in a <Suspense> boundary using this file as the fallback.

// app/posts/loading.tsx
export default function Loading() {
  return <div className="animate-pulse">Loading posts…</div>
}

Not Found Handling

↑ Index

not-found.tsx

Rendered when notFound() is called from next/navigation, or when no route matches.

// app/posts/[id]/not-found.tsx
import Link from 'next/link'

export default function NotFound() {
  return (
    <div>
      <h2>Post not found</h2>
      <Link href="/posts">Back to posts</Link>
    </div>
  )
}

Place it at app/not-found.tsx for a global 404 page, or inside any route segment for a scoped one.


API Routes

↑ Index

route.ts

Defines a serverless API endpoint using HTTP method handlers.

// app/api/posts/route.ts → accessible at /api/posts
import { NextResponse } from 'next/server'

export async function GET() {
  return NextResponse.json({ message: 'Hello' })
}

export async function POST(request: Request) {
  const body = await request.json()
  return NextResponse.json(body, { status: 201 })
}

A folder cannot contain both route.ts and page.tsx.


Dynamic Route Segments

↑ Index

ConventionURL ExampleParams
[id]/posts/123{ id: '123' }
[...slug]/docs/a/b/c{ slug: ['a', 'b', 'c'] }
[[...slug]]/docs or /docs/a/b{ slug: undefined } or { slug: ['a', 'b'] }
// app/posts/[id]/page.tsx
export default async function PostPage({
  params,
}: {
  params: Promise<{ id: string }>
}) {
  const { id } = await params
  return <h1>Post {id}</h1>
}

Next.js 16 change: params is now a Promise — you must await it.


Route Groups & Parallel Routes

↑ Index

Route Groups — (folder)

Organize routes without affecting the URL.

app/(marketing)/about/page.tsx   → /about
app/(shop)/products/page.tsx     → /products

Use cases: sharing a layout across a subset of routes, keeping the file tree organized.

Parallel Routes — @slot

Render multiple page components simultaneously in the same layout.

app/@analytics/page.tsx
app/@team/page.tsx
app/layout.tsx        ← receives { analytics, team } as props

Intercepting Routes

↑ Index

Used for modals and advanced navigation (e.g. opening a photo in a modal while keeping the URL).

ConventionIntercepts
(.)segmentSame level
(..)segmentOne level up
(...)segmentFrom the root
app/feed/(.)photo/[id]/page.tsx

This is an advanced pattern — most apps don't need it.


Proxy (formerly Middleware)

↑ Index

proxy.ts (Next.js 15.2+)

The modern replacement for middleware.ts. Located at the project root.

// proxy.ts
import NextAuth from 'next-auth'
import { authConfig } from './auth.config'

export const { auth: middleware } = NextAuth(authConfig)

proxy.ts runs before a request reaches your route. Common uses:

  • Authentication — redirect unauthenticated users
  • Redirects — map old URLs to new ones
  • Headers — add security or CORS headers

What changed: In Next.js versions before 15.2, this file was called middleware.ts. The old name still works as a fallback, but proxy.ts is the recommended convention going forward. We covered this migration in Step 22.


Static Metadata Files

↑ Index

These are generated at build time from TypeScript/JavaScript files inside app/.

FileGeneratesExample
robots.tsrobots.txtexport default function robots() { ... }
sitemap.tssitemap.xmlexport default function sitemap() { ... }
manifest.tsmanifest.json (PWA)export default function manifest() { ... }
opengraph-image.tsxOG imageDynamic image generation
icon.tsxFaviconDynamic icon generation

You can also use the Metadata API directly in layout.tsx or page.tsx:

// Static metadata
export const metadata = {
  title: 'My App',
  description: 'Built with Next.js 16',
}

// Dynamic metadata
export async function generateMetadata({ params }) {
  const { id } = await params
  const post = await getPost(id)
  return { title: post.title }
}

Project Config Files

↑ Index

These live at the project root, not inside app/.

FilePurpose
next.config.tsNext.js configuration (redirects, images, env, etc.)
instrumentation.tsObservability and tracing hooks (stable since Next.js 15)
proxy.tsRequest interception (auth, redirects, headers)

Deprecated Conventions

↑ Index

Old ConventionStatus in Next.js 16Modern Replacement
head.tsxRemovedexport const metadata or generateMetadata() in page.tsx / layout.tsx
middleware.tsDeprecated (still works)proxy.ts at project root
pages/ directoryLegacy (Pages Router)app/ directory (App Router)
_app.tsx, _document.tsxLegacy (Pages Router)app/layout.tsx
getServerSideProps, getStaticPropsLegacy (Pages Router)async Server Components + fetch / Prisma directly

What You Actually Need

↑ Index

Most real-world Next.js 16 apps use only these files:

FileWhy
page.tsxEvery route needs one
layout.tsxShared navigation, providers, metadata
loading.tsxInstant feedback while data loads
error.tsxGraceful error handling
not-found.tsxCustom 404 pages
route.tsAPI endpoints (when needed)
proxy.tsAuthentication and redirects

The advanced conventions (template.tsx, default.tsx, parallel routes, intercepting routes) are powerful but only needed for specific use cases.


Summary & Key Takeaways

↑ Index

ConceptDetails
File-based routingA folder becomes a route only when it has page.tsx
Layouts persistlayout.tsx doesn't remount; template.tsx does
Error boundarieserror.tsx (per-segment) and global-error.tsx (root) — both Client Components
Loading statesloading.tsx = automatic <Suspense> fallback
API routesroute.ts with named HTTP method exports (GET, POST, etc.)
Dynamic segments[id], [...slug], [[...slug]]params is a Promise in Next.js 16
Route groups(folder) for organization without URL impact
Proxy replaces middlewareproxy.ts is the Next.js 16 convention; middleware.ts is deprecated
Metadata APIexport const metadata or generateMetadata() — replaces the old head.tsx
Config filesnext.config.ts, proxy.ts, instrumentation.ts live at project root

Further reading