Chris.luChris.lu header image, displaying an 80s style landscape and sunset

First Typescript page

I hope you are still there because it is finally time to start coding (a bit) 🙂, but first a bit of theory about routing 😉 (feel free to skip the first chapter if you know it already), and then we create our very first page

Next.js routing/pages

If you used the Next.js pages router in the past but did not yet use the app router, then here is a short introduction

With the pages router, if you wanted to have a page at www.example.com/foo, then you would create a file named foo.tsx inside of the pages folder

With the app router if you want a page at that same www.example.com/foo path, then you create a folder named foo inside of the app folder (and add a page.tsx file inside of it)

Let's assume the path is now www.example.com/foo/bar, when using the pages router foo would be a folder inside of pages, but bar would be a file, however, when using the app router, every segment is a folder

The other difference are the page files, with the pages router, the name of the file gets used as the last segment of a URL, in the app router, every page is always named page(.jsx/.tsx) and all directories will be a segment of the URL

The advantage of using a folder as the last segment and having a convention that says that every page needs to be named page(.jsx/.tsx) is that with the introduction of the app router Next.js added a bunch of other file conventions, for example you can have a layout in every segment folder, you can have a not-found file in every folder and so on, meaning you can create different layouts for different parts of the website easily, or even create different error, loading, not-found, ... pages for various parts of your project (without having to add logic inside those files to check what the current path is and then show a different layout, UI or content based on what the path is)

A feature you will already know if you used the pages router is dynamic routes. To create a dynamic route segment, you wrap the folder's name in square brackets, for example, with a folder structure like this /app/articles/[slug], the slug could be anything, so if the URL is www.example.com/articlers/foo then the slug have "foo" as value and for another URL www.example.com/articlers/bar the slug would be a "bar", to retrieve the slug value you would create a page with the following code:

/app/articles/[slug]/page.tsx
export default function Page({ params }: { params: { slug: string } }) {
    return <div>My article slug is: {params.slug}</div>
}

Other useful features were introduced with the new router, like route groups which we will see in a future part of this tutorial. Another new feature are parallel routes, which I will not cover them in this tutorial, but it is good to know they exist as they might become useful sooner or later as your project grows

If you haven't read my The road to React 19 and Next.js 15 post yet but want to know more about the Next.js pages VS app router, then you might want to check out the "pages VS app router" chapter

Our 1st typescript page

Start by opening the app folder, which create-next-app created for us during the initial setup of our project

If you have a bit of time, have a look at what Next.js has put in there (it's always good to have a look at what the Next.js team recommends), but after that, delete all the files in the /app folder as I want to go step by step through the process of creating a Next.js blog, you can also delete the content in the /public folder as we won't need the assets of the demo project anymore

Next, create a new file in the app folder and name it page.tsx (or page.jsx if you choose to use javascript)

Then add the following content into the page.tsx file and finally save it

/app/page.tsx
export default function Home() {
 
    return (
        <>
            <h1>Hello World?</h1>
        </>
    )
 
}

Congratulations 🎉 you just coded your first Next.js page in typescript, next we will make sure the page actually works

Start the dev(elopment) server

Now open the VSCode terminal if it isn't open yet (or use your favorite command line tool), and let's use one of the 4 commands create-next-app added to the package.json scripts (and which we documented in README.md earlier) to start the development server:

npm run dev

Now, in the terminal, press Ctrl and then click on the Next.js local server URL or open your browser and put the following URL into the address bar: http://localhost:3000/

As you can see, Next.js has compiled our typescript page, and the development server has responded to the browser request, which is why we can see our "Hello World?" message

The root layout is required

Go back to VSCode and look at the list of files in the sidebar

You will notice that Next.js re-added the /app/layout.tsx file (when we started the dev server) we just deleted earlier. This is because this layout file is called the root layout and it is required (and because Next.js is a clever framework that in many places helps you do the right thing 😉), also if you look at your VSCode terminal you will see that Next.js printed the following line, informing us that it created the layout file for us:

âš  Your page app/page.tsx did not have a root layout. We created app\layout.tsx for you.

If you open the /app/layout.tsx file, you will see that on top, there is the following code:

/app/layout.tsx
export const metadata = {
    title: 'Next.js',
    description: 'Generated by Next.js',
}

As you can see, Next.js has added a metadata object, this is the Next.js metadata API that we will soon use in layouts and pages to set the tags in the <head> element, like the title and description (I will go more in detail in a future chapter) but also open graph tags

The second part it has added is just a basic Next.js RootLayout function that adds basic HTML elements and the children prop that will contain the content of the pages that get wrapped by the layout:

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

This layout is still very basic, it only contains the bare minimum of HTML elements to create a valid HTML document, but in future chapters we will add more code to make this layout file more useful

Edit the first page

As you might have noticed, I added a question mark in the Hello World? heading text

Let's replace the question mark with an exclamation mark and then save the file:

/app/page.tsx
export default function Home() {
 
    return (
        <>
            <h1>Hello World!</h1>
        </>
    )
 
}
Note

As soon as you save the file, you will see in the terminal that Next.js prints a message Compiled in Xms (Y modules), which shows you that Next.js detected changes in your code base and did a new build for you

Now go back into your browser to have another look at the rendered page using the (https://localhost:3000/) URL

Even though you haven't reloaded the page manually, you will notice that your changes have been applied, which is because Next.js has a feature called fast refresh, this feature will watch your code base and each time a page gets rebuilt it will also refresh the page in the browser

Next.js Hot Module Reload (HMR)

Let's go back to our project, make sure the dev server is running or use the npm run dev command to start it and then open http://localhost:3000/ in your browser

In your browser right click somewhere on the page and then select Inspect (or open the browser dev tools by pressing the F12 and then open the Elements tab), you will see that Next.js injects a bunch of Javascript code into our page and some of those javascript files are heavy, this is because Next.js adds, for example, a tool called Hot Module Reload (HMR) (all the HMR code won't get loaded in production, Next.js only adds those files to our page when in development mode)

HMR starts watching for file changes as soon as you start the development server

If we edit and save (or add a new file), HMR will detect the change and tell Next.js to (re-)compile the files, then Next.js fast refresh will update the output in the browser for us

Stop the dev(elopment) server

We started the development server earlier, but how do we stop it? If you have never done it before, it might not be obvious how to do it

The easiest way to stop the development is to press Ctrl+S (macOS: ⌘S, Linux: Ctrl+S)

Then you will get asked if you want to quit:

Terminate batch job (Y/N)?

To confirm, either enter Y and then press ENTER or just press Ctrl+S (macOS: ⌘S, Linux: Ctrl+S) again