Root Layout

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?

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 root app/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 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 uses app/(shop)/layout.js to /blog that uses app/(marketing)/layout.js will cause a full page load. This only applies to multiple root layouts.

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).