Next.js Layouts RFC: The Route to the app Directory

Vercel's Next.js team has published the Layouts RFC, outlining the future of routing, layouts, and data fetching in the framework. The proposal is dense, but the core concepts are straightforward. Here is what developers need to know before the changes land in the next major release.

Routes as Folders, Pages as Files

The upcoming architecture introduces an app directory where folders define routes. Each folder becomes a segment in the URL path. To make a segment reachable, add a page.js file inside it, such as app/page.js for the root path.

export default function Page() {

return <h1>Hello, Next.js!</h1>

}

These well-known folders and files map directly to URL segments. The pages directory continues to work, meaning teams can adopt the app directory incrementally without rewriting existing applications.

Layouts Are Just Files

Shared UI is handled through layout.js files. Placing a layout in a folder applies it to all pages beneath that segment. A root layout at app/layout.js wraps every page in the application.

Creating routes using pages and layouts.

A root layout is the first file a developer creates, often containing global shell elements:

export default function RootLayout({ children }) {

return (

<html>

<head>

<title>Next.js Layouts RFC in 5 Minutes</title>

</head>

<body>{children}</body>

</html>

);

}

In this model, a page is not the full document but a child of its layout:

<html>

<head>

<title>Next.js Layouts RFC in 5 Minutes</title>

</head>

<body>

<h1>Hello, Next.js!</h1>

</body>

</html>

Nested layouts are created by adding more layout.js files deeper in the tree. For example, a app/blog/layout.js layout applies only to pages under app/blog/:

export default function BlogLayout({ children }) {

return (

<>

<aside>

<nav>...</nav>

</aside>

{children}

</>

)

}

The framework composes these files into a hierarchy. An individual blog post at app/blog/[slug]/page.js sits under both the root layout and the blog layout, receiving their combined UI:

export default function IndividualBlogPost() {

return (

<main>

<h1>Routing with Next.js</h1>

<p>Lorem ipsum dolor sit amet</p>

</main>

)

}

Suspense and Error Boundaries for Free

Loading states are declared in loading.js. Next.js automatically wraps the page or nested segment in a React Suspense boundary and renders the loading component — on the first request and during navigation between sibling routes.

The Next.js Loading UI creates a React Suspense boundary.

Errors work similarly. A file named error.js becomes a React Error Boundary for its subtree, letting errors be isolated to a specific section. Developers can then show contextual error information and attempt recovery clientside without tearing down the rest of the page.

The Next.js Error UI creates a React error boundary.

Route Groups for Cleaner URLs

Route groups solve three problems:

  • Keeping routes organized on disk without adding URL segments
  • Excluding segments from an inherited layout
  • Supporting multiple root layouts in one app for visually distinct sections
You can exclude routes from layouts using route groups.

By wrapping a folder in parentheses, files inside still generate routes, but the group name stays out of the URL path.

The RFC is open for review at nextjs.org/blog/layouts-rfc.