Pages and Layouts

Why do Next.js pages make lousy customs officers?
Because they keep exporting everything.
— From "1000 programming dad-jokes"

Pages

Next.js uses file-based routing. This means that folders are used to define routes and each folder represents a route segment (which maps to a URL segment).

You can define nested routes by nesting folders inside each other.

For example, the folder about would represent the route /about (which would be mapped to the URL /about). On the other hand, a folder about inside a folder company would represent the route /company/about (which would be mapped to the URL /company/about).

Note that all of this is relative to our root directory (which in our application is src/app). This means that the route /about would actually be located at src/app/about and the route /company/about would actually be located at src/app/company/about.

Routes can have special files, which are used to actually define the route. For example, the special page file (which can be e.g. page.js, page.jsx or page.tsx) is used to display the UI for the given route. For this to work, the page file needs to default export a React component.

We already have a route with a special page file—namely src/app/page.tsx which defines the UI to be displayed for the (root) route /:

export default function Home() {
  return <h1>Welcome</h1>;
}

If you go to http://localhost:3000/, you will see the text Welcome, because that's the UI that is defined in the default exported React component.

Let's create another page. Add a new directory about in src/app and create the following file src/app/about/page.tsx:

export default function About() {
  return <h1>About</h1>;
}

Go to http://localhost:3000/about and you will see the text About.

From now on we will stop prefixing everything with src/app and simply assume that you are always in src/app. For example, if we tell you to create a file task/route.ts you should actually create the file at src/app/task/route.ts.

Layouts

A page defines the UI that is unique to a route. You can also define UI that is shared between multiple pages. This is called a layout in Next.js.

You define a layout by default exporting a React component from a layout file (e.g. layout.tsx). The component should accept a children prop that will be populated with a child layout or a child page.

Let's go to the layout.tsx file in the root directory, which currently looks like this:

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>{children}</body>
    </html>
  );
}

Let's change it to:

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        <header>My header</header>
        {children}
      </body>
    </html>
  );
}

Now the header "My header" will appear on every page (i.e. both on / and /about).

After you've verified this, you can remove the header again.

Note that the top-most layout (which must always be present) is called the root layout and will be shared across all pages. The root layout must contain html and body tags.

The root layout is also where you define metadata. This can be done by exporting a metadata object in the root layout file:

export const metadata: Metadata = {
  title: 'Example Application',
  description: 'My example application',
};

You can add navigation between routes by using the <Link> component.

This is a component built on top of the HTML <a> tag that you already know. However, this component does some additional things, like prefetching (i.e. preloading routes in the background). It also changes the way navigation works (we will talk more about this in the next sections).

For example, you could add a link to the /about page from the / page by changing the content in page.tsx to this:

import Link from 'next/link';

export default function Home() {
  return (
    <>
      <h1>Welcome</h1>
      Go to the <Link href="/about">About</Link> page
    </>
  );
}