Root Layout
Let's dive into another significant change introduced in Next 13: the Root layout. What exactly is the Root layout, and what specific changes have been implemented in this new version?
A root layout is the top-most layout in the root app
directory. It is used to define the <html>
and <body>
tags and other globally shared UI.
Key Highlights
- The
app
directory must include a rootapp/layout.tsx
. - The root layout must define
<html>
and<body>
tags.- You should not manually add
<head>
tags such as<title>
and<meta>
to root layouts. Instead, you should use the Metadata API (opens in a new tab) which automatically handles advanced requirements such as streaming and de-duplicating<head>
elements.
- You should not manually add
- You can use route groups (opens in a new tab) to create multiple root layouts.
- Navigating across multiple root layouts will cause a full page load (as opposed to a client-side navigation). For example, navigating from
/cart
that usesapp/(shop)/layout.js
to/blog
that usesapp/(marketing)/layout.js
will cause a full page load. This only applies to multiple root layouts.
- Navigating across multiple root layouts will cause a full page load (as opposed to a client-side navigation). For example, navigating from
Transition from _app.tsx
to layout.tsx
In Next 12, we used the _app.tsx
file to specify the root of our project, which served as the main entry point for our application. However, in Next 13, we no longer have that. Instead, we have the new layout.tsx
. It serves the same purpose as the _app.tsx
file.
import './globals.css'
import { Inter } from 'next/font/google'
const inter = Inter({ subsets: ['latin'] })
export const metadata = {
title: 'Create Next App',
description: 'Generated by create next app',
}
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body className={inter.className}>{children}</body>
</html>
)
}
Root Component
In Next 13, we export a default component in layout.tsx
which will be the root layout, It receives children
as props, similar to how it’s done in _app.tsx
. This allows us to structure our HTML document by directly including the html
and body
tags. Such a level of control was not available in Next 12, where the generation of these tags was handled internally.
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body className={inter.className}>{children}</body>
</html>
)
}
Metadata
There is a new and simplified way to define the metadata of our application. We can now export an object with each field representing a specific metadata attribute. This makes it easier to manage and update the metadata for our app:
export const metadata = {
title: 'Create Next App',
description: 'Generated by create next app',
}
The metadata
object and generateMetadata
function exports are generated on the server and only supported in Server Components. You can’t use the Head component in the new app
router:
// This doesn't work, the meta tags won't show up.
import Head from "next/head";
const metadata = {
title: 'Create Next App',
description: 'Generated by create next app',
}
function MyPage() {
return (
<>
<Head>
<title>{metadata.title}</title>
<meta name="description" content={metadata.content} />
</Head>
</>
);
}
export default MyPage;
Metadata can be either static or dynamic:
import { Metadata } from 'next';
// Static metadata
export const metadata: Metadata = {
title: '...',
description: '...'
}
// Dynamic metadata
export async function generateMetadata({ params }) {
return {
title: '...',
description: '...'
};
}
Dynamic metadata allows for greater flexibility and customization. For example, you can query the page title from a database for each page. For further information about metadata in Next.js and to explore additional details for the metadata, refer to the official documentation (opens in a new tab).