Take Your Next.js 13 App to the Next Level with New Routing Enhancements, Dynamic Layouts, and Efficient Links
We will look at pages, layouts, some routing, and linking with Next.js 13
In this series, we’re continuing through the basics of learning the new features of the static site generator, Next.js 13.
Introduction
In the previous lesson, we learned how to start a new Next.js 13 project and reviewed all the files you get.
Today we'll dig deeper and look at how we can construct pages and layouts in the new Next.js 13 app directory, and we'll also look at some basic routing.
Prerequisites
If you intend to follow along with this tutorial on your system, please ensure you have the following:
A basic understanding of working with the terminal.
A Laptop or PC with Windows installed
An Internet connection
Git is installed on your local machine (optional). For more details on accomplishing this, review Installing & Setting Up Git on Windows.
A GitHub account. For more details on accomplishing this, review How to get started with Git and GitHub
The latest version of Visual Studio Code is installed on your machine.
Basic knowledge of HTML, CSS, JavaScript, and React.
Note: This is a follow-up tutorial, it does require you to have created the "1. Getting Started" tutorial, as covered in the article Getting Started with Next.js: A Comprehensive Guide to Building Your First Application to make the most of it.
Let’s get started!
Creating a Starter Project
You can see we've got Visual Studio Code open, where our completed code for the previous part nextjs-one of this beginner series is, which is essentially the starter project that you get after you install Next.js 13.
Let's get started by making a copy of nextjs-one and renaming the file to nextjs-two inside our nextjs-series directory.
I'm going to open up this nextjs-two directory with Visual Studio Code and we can see everything that was installed from nextjs-one is over here in the file tree, but we need to change some of the contents of the package.json
file,
and the packages.lock.json
file as well.
Routing between pages
Now, just to recap quickly, we changed the contents of the home page, the page.tsx
file, the default page, and if you followed along with part one, that's in the new app directory for Next.js 13.
In this app directory, let's create another directory inside of it, and let's call this directory about. Inside the about directory let's create another page.tsx
file.
To create a new page.tsx
file here and put that inside a directory called about, rather than first creating the about directory and then creating the new file inside of that, we can just click the new file button and then type about/page.tsx
and hit enter. We can see when that file within that directory was created.
If we type RFC for react functional component and see that choice right there, we're going to select that.
Note that's not part of Next.js 13 -that is an ES7 react Snippets extension that we can use, we just need to head over Extensions and we're going to search for VS Code ES7+ React/Redux/React-Native/JS snippets
This extension is very good with those snippets, so you can type those abbreviations and complete those functional components very easily.
If we go back to the project, we have our basic functional component for the page, but we could name it About with a capital letter.
import React from "react";
export default function About() {
return <div>page</div>;
}
If we look back at the older page.tsx
file notice they didn't name this page either; it's named Home so we want to name the functional component what it actually is, about however the page itself is named page.tsx
. We go ahead and save the page.
This is how basic routing and pages are created in Next.js 13.
Accessing the Development Site
So let's go ahead and open a terminal window, and I'm going to type in the following:
npm run dev
In the meantime, when we want to have a different page that we could link to or navigate to, we want to create a directory for that page. Now, if we look at our page, you can see we're just returning a <div>
that says: page.
We would go to http://localhost:3000
and then navigate to /about
, and if we press enter, we have the word page displaying there (it's very small) at the top left corner.
We could change what we have in here; maybe we make it a little bit bigger, maybe even apply just some CSS, but we know we do have a second page now, and we can navigate to it with /about
.
If we go back to the home page, we're going to make one simple change here, and that is to turn this <div>
into a header <h1>
, it's a little bit bigger and easier to see, and then we going to turn the word page into the word About, with capital letter ‘A’, so we know we're on the about page.
import React from "react";
export default function About() {
return <h1>About</h1>;
}
Creating a root layout component
Let's look at the layout.tsx
file that's in the parent app directory and for this layout.tsx
applies to the entire site or the entire application, so anything we would put there, would be affected on every other page as well.
For example, we could add an <nav>
element, not by creating a separate component but just inside the <body>
here, and if we look better, the body returns all of the child components inside of the application, but then we could have a component above that we defined, so if we created a navbar element in a separate component, we could import that and that would work as well, but for now we're just going to use the <nav>
element and then inside of the <nav>
element we're going to add an h1
and with the text Navbar and save.
return (
<html lang="en">
<body>
<nav>Navbar</nav>
{children}
</body>
</html>
);
If we can look at the application running on http://localhost:3000
we have Navbar there at the top left corner of our Home page
but if we click forward to /about
page, we also have that Navbar on the /about
page, so this parent layout.tsx
applies to all the pages on the application.
Creating a nested layout component
We want to create another layout, that will only apply to anything in the about folder or better yet, the about tree, which means it will only apply to any pages that start with the /about,
and of course, we could have sub-directories and other pages that follow that path. For example, we could have a sub-page or directory in the about directory.
We're going to create another layout.tsx
file inside of the about directory.
Let's start again by typing RFC, If we notice the function is not going to have the name layout, but that's not what we want, right?
Let's look back at what we were given from our earlier starter files, and we can see this was named RootLayout.
We're copying (Ctrl + C) from the beginning of the RootLayout and going down to the return with the parentheses included.
RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
We head over to our newly created layout.tsx
, and we'll return something different, but we need the same types, and we'll need to change the name to AboutLayout.
Let's paste (Ctrl + V) the code we copied above in there and Rename it to AboutLayout.
export default function AboutLayout({
children,
}: {
children: React.ReactNode,
}) {
return <div>layout</div>;
}
Notice in the return of the parent directory for app, that the starter file layout.tsx
it has the <html lang="en">
. We only want one of those per page, and really per site because this applies to everything. Anything we have below is considered a child {children}
and it's right here in our HTML structure.
return (
<html lang="en">
{/*
<head />
will contain the components returned by the nearest parent head.tsx. Find out
more at https://beta.nextjs.org/docs/api-reference/file-conventions/head */}
<head />
<body>
<nav>
<h1>Navbar</h1>
</nav>
{children}
</body>
</html>
)
Going back to our new layout.tsx
inside the about directory, we could just start with a fragment.
export default function AboutLayout({
children,
}: {
children: React.ReactNode,
}) {
return (
// FRAGMENT
<></>
);
}
Now we put a nav element and we can call this the About Navbar After this <nav>About Navbar</nav>
, let's go ahead and put a <main></main>
element inside. The <main></main>
element is where we'll put the {children}
for this AboutLayout.
To finish this, we'll go ahead and save that file.
The file layout.tsx
will look like this:
export default function AboutLayout({
children,
}: {
children: React.ReactNode,
}) {
return (
<>
<nav>About Navbar</nav>
<main>{children}</main>
</>
);
}
In our browser again, looking at the home page, let's go to the URL and add /about
.
http://localhost:3000/about
Now we have the Navbar that applies to the entire application, then we have the About Navbar under that, and lastly, we have the word About underneath.
Note: We can use the forward and back buttons to navigate between pages.
Adding links to pages
Let's go and add some links to our pages to navigate between the two as well, so I'll come back to Visual Studio Code. Let's visit the page inside of the about directory and we'll add a link there first, so at the top of the page I need to add:
import Link from "next/link";
If you're familiar with react-router, this is a lot like using react-router when we import a link there from that library.
After we add the import we're going to add a fragment here and put an <h>
inside of that fragment.
<>
<h1>About</h1>
</>
I'm just going to <Link>
this back to the home page, so that's just the "/"
for the root directory, and then we'll have a link to the home page just for the text.
<Link href="/">Link to Home Page</Link>
The about/page.tsx
file should now look like the following:
import Link from "next/link";
export default function About() {
return (
<>
<h1>About</h1>
<Link href="/">Link to Home Page</Link>
</>
);
}
When we save the file, we can see in the browser if that link has been added, so we need to go forward to our /about, and there it says: Link to Home Page and yes, we get a pointer with our cursor, and when we click that, we go back to the home page.
Now let's do the same for the home page. When we come back to the page.tsx
in the app directory app/page.tsx
, notice not inside the about directory,
and here we can import a link as well.
import Link from "next/link";
Just underneath the Hello, welcome we'll put another link there.
<h1 className={inter.className}>Hello</h1>
<h2 className={inter.className}>Welcome to...</h2>
I am going to add a line break and type Go to About Page between Link and save the file.
<br />
<Link href="/about">Go to About Page</Link>
The app/page.tsx
file should now look like the following:
After saving, we can see in the browser that the Go to About Page link has been added, so we need to go forward to our /about, and there it says: Link back to Home Page as we saw before, and yes, we also get a pointer with our cursor, and when we click that, we go forward to the about page.
Conclusion
In this article, we learned how to use the new experimental app directory in Next.js 13. We also saw how we create new pages within the app folder and how we create another folder within the app directory where we can create more pages, route them, and link to them.
The patterns and conventions we learned in this article are still experimental features that Next.js 13 is implementing while moving forward, however, they are already very useful, and we can already start using them in our projects
Next.js 13 is constantly incrementing these new features and adding some new ones, so I'll try to cover those if they continue during this beginner series; however, I prefer to publish the new features rather than the previous ones, because this is the direction that Next.js 13 is headed in the future.
What's next?
During our upcoming part 3, we will delve into the topics of CSS modules, adjustments with metadata, and loading. It is important to prioritize progress rather than perfection, as even small advancements made each day can lead to significant results.
Thanks for the read! Now go practice & build something awesome!