3 min read

Getting started with the Next.js 13 app directory

The Next.js app directory offers a total overhaul of how to build applications.
Next.js App Directory
Next.js App Directory

Next.js 13 introduces a complete overhaul of how you can build applications. This new feature is simply called the "app directory" (great marketing, Vercel), but it totally changes how you can and should build applications.

The app directory is opt-in for Next.js 13, although, in the future, it will become the default. The old pages directory is still supported.

But you're here to use the new shiny feature, so let's dive in.

What are the big differences?

The app directory unlocks server components.

Server components are regular React components but only rendered on the server. Until now, all Next.js components might be rendered on the server or the client.

This limits what you can do with them.

With server-only components, you unlocked new powers.

Because they are only executed on the server, you have the entire server API available. For example, you can read files, access the database, or make a request to a protected API.

A server component is a React component that returns a Promise of JSX. This lets you use async/await in your server components.

Pretty fucking cool. It looks like this:

const MyComponent = async () => {
  const posts = await db.findAll({ where: { published: true } })
  return (
    <ul>
      {posts.map((post) => (
        <li key={post.id}>{post.title}</li>
      ))}
    </ul>
  )
}
React Server Component

The resulting React component is streamed to the client when it is rendered.

What else is unlocked with the app directory?

There is a new router and routing layout that is used. The new files let you build nested layouts:

  • layout.tsx Defines the layout for all pages in its path.
  • head.tsx Defines the <head> for a page.
  • page.tsx Defines the page itself.

Similar to the pages directory of old, you use folders to create your route paths. It's important to note that you can't use any name for a page anymore. You must name each page page.tsx and use folders to define the route.

Lastly, the app directory does not have API routes. Those will still need to go in the pages/api directory for now.

Getting Started

Fire away:

yarn create next-app

This will walk you through creating your project name. It will ask if you want to use the app directory, and you should type y for yes!

You should also use TypeScript and ESLint.

I don't recommend using the src directory. Why nest things more?

If you want a 1 liner for this, you can type:

yarn create next-app --ts --eslint --no-src-dir --import-alias "@/*" --experimental-app <PROJECT_NAME_HERE>

Poking around

You can now cd into your project and take a look around. Some quick notes:

  • The public directory is the same as before, where you can put static files.
  • The pages directory only contains the api folder. The rest of the content has been moved to app.

The app directory

This is where the fun is!

Because the app directory now has specific file names for each part of the page (page,  layout, and head), you can co-locate other files, such as CSS and component files.

You can define CSS anywhere in this directory and then import it into your layout or page files.

Layout

A layout is a template that defines the structure of all children pages. It takes children as a prop, and you must pass that through. The root layout will contain the root <html> tag, but other nested layouts should not.

The simplest layout looks like this:

export default function Layout({ children }: { children: React.ReactNode }) {
  return children
}
The simplest layout, which lays out nothing

Simple, yes. Effective, no. Your layouts will most likely define navigation and other common components.

Page

The page file must export a default React component. It may be async as well, which unlocks the ability to use await in the component to load data.

For creating routes, the folder structure defines the path:

app/page.tsx => /
app/login/page.tsx => /login
app/(group)/dashboards/page.tsx => /dashboards
app/users/[id]/page.tsx => /users/5
Folder paths map to URLs

It functions similarly to how the pages directory works.

Development

As always, to start hacking and see your changes, run:

$ yarn dev

Congratulations! You can now code into the future. If you're looking for some good next steps, I recommend installing Tailwind and configuring Prettier.