Checkout my CSS Grid By Example and Getting Started With React video courses on Skillshare. Sign up now and get one free month of Skillshare.

First app with NextJs 13: setup, the new /app folder, and routing system

NextJs 13 comes with a great set of new features. One of the major additions is the new /app folder as the root folder for the pages of our app. This determines also changes to the NextJs routing conventions.

The plan for this article is to build a simple store app with the following URL structure:

/              -> points to a basic static Index page
/products      -> points to a basic root static Products page
/products/_id_ -> points to a parameterized product page
/about         -> points to a static About page

In this article we will cover the following:

  • setting up a NextJs 13 project from scratch
  • using the /app folder to serve static pages
  • using query params in NextJs 13

Let's start learning!

Setting up a NextJs 13 project from scratch

Before we start the actual coding will need to set up the project.

Will start from scratch by creating an empty folder namednext13-jscraft-first. Inside this folder will first run the npm init command to create the package.json file with the default values:

npm init -y

Next, we will need to install the minimum required dependencies:

npm install next@latest react@latest react-dom@latest eslint-config-next@latest 

Given that NextJs 13 is still experimental will need to create a next.config.js file in the root of the out project with the following content:

 * @type {import('next').NextConfig}
module.exports = {
        appDir: true

Finally, open the package.json and in the scripts section add the below lines:

"build": "next build",
"start": "next start",
"dev": "next"

Using the /app folder to serve static pages

Before, we can see the first page of our new NextJs 13 project will need to create the /app folder at the root of our project.

The /app folder comes as a replacement for the /pages folder. For the moment, we can still use both of them so that we can have a smother upgrade to NextJs 13.

To define the main index page of our store app we will add a /app/page.js file.

At this point, our app should have the following files and folders:


In NextJs 13 page.js is a reserved filename and maps to the default entry page of a folder. Now, we can put other things in a subfolder of /app, not just javascript pages. We can add styles, subcomponents, or tests. NextJs needs this reserved page.js name to know what file to load first from a given folder.

For our /app/page.js we will just add a simple heading:

/* /app/page.js */
export default function Index() {
    return (
        <h1>🏡 The Home Page</h1>

With all of this in place, if we now run npm run dev we will see the below page up and running at http://localhost:3000/:

When we first run npm run dev you will see that two new items were added to our project folder:

  • a new autogenerated app/layout.js file. As the name implies it contains the layout description for our app. It replaces /pages/_app.js and /pages/_document.js files from the older versions of NextJs
  • the .next folder contains the build files (this was also present in the older Nexjs versions)

By the way, if you are interested to find out more about NextJs 13 and other frontend tips you can sign up for my newsletter. You can check out here and here some examples of the js-craft newsletter.

In order to add a second page to our app we will create a new folder app/about. We will need an entry point for this folder, meaning that we will need to add a page.js file. The content of app/about/page.js will be:

/* /app/about/page.js  */
export default function Index() {
    return (
        <h1>🏡 The About page</h1>

Now, if we visit http://localhost:3000/about we will see the newly created page:

Using query params in NextJs 13

So far, so good! But we have just used plain old static pages. What if we want to have URLs with the following format:


In order to add a query param to a route the convention is to create a new folder and wrap that query param name in square brackets.

We will name our query param id. So, we will create a new subfolder of /app called /products. And inside of /app/products, we will add a [id] subfolder containing the page.js file:

/* /app/products/[id]/page.js */
export default function ProductWithId({ params }) {
return (<h1>📦 Individual product with id: {} </h1>

Having this new page if we visit an URL like http://localhost:3000/products/123 we will see this output:

Keep in mind that we can still add a page.js in the root of our app/products folder:

/* /app/products/page.js */
export default function ProductIndex() {
    return (
        <h1>🛒 Products Page</h1>

And it will be accessible at the root of http://localhost:3000/products:

If you need to create links between these pages you can still use the Link component as before Next 13.

You can see the full code here

Home Screencasts Best of Newsletter Search X