Back to Blog
Lesson 2 of the Next.js: Build Full-Stack Apps with the App Router course
Next.jsJuly 13, 20264 min read

Understanding the App Router Architecture: A Beginner's Guide

Master the Next.js App Router by learning how the filesystem acts as your router. Discover the difference between page.js and layout.js.

Next.jsApp RouterRoutingWeb DevelopmentReact

Previously in this course, we covered how to set up your first Next.js project. Now that you have a running development server, it’s time to move beyond the default "Hello World" and understand the core engine of modern Next.js: the App Router.

In older web frameworks, you often had to maintain a separate configuration file that listed every URL path and the component that should render for it. If you had 50 pages, you had a 50-line file that was prone to drift. The Next.js App Router takes a different approach: filesystem-based routing. Your folder structure is your URL structure.

Mapping URLs to the Filesystem

In the app/ directory, every folder represents a route segment. To make a segment publicly accessible, you must place a special file—usually page.js—inside that folder.

Consider this directory structure:

TEXT
app/
├── page.js          // Matches the root URL: /
├── about/
│   └── page.js      // Matches the URL: /about
└── contact/
    └── page.js      // Matches the URL: /contact

If you want a nested route, like /about/team, you simply nest the folders:

TEXT
app/
└── about/
    └── team/
        └── page.js  // Matches the URL: /about/team

This intuitive mapping means that as you build your blog, you don't need to search through configuration files to find where a page is defined. You just navigate to the folder corresponding to the URL.

page.js vs. layout.js

You will notice two primary file names appearing constantly in the app directory. While they both contain React components, they serve very different roles in the UI.

File TypePurposeBehavior
page.jsThe unique UI for a specific route.It is the leaf node of the route segment.
layout.jsThe shared UI across multiple pages.It wraps child layouts and pages.

A layout.js file is essential for maintaining consistency. For example, if you want your blog to have a persistent header and footer, you don't repeat that code in every single page. Instead, you define it in a layout. When a user navigates between pages within that same layout, the layout remains mounted, preserving state and preventing unnecessary re-renders.

Worked Example: Building the Blog Structure

Let’s advance our running project by setting up the initial structure for our blog. Open your project and navigate to the app/ directory.

  1. Delete the default content in app/page.js and replace it with a simple homepage heading:

    JSX
    // app/page.js
    export default function HomePage() {
      return <h1>Welcome to My Blog</h1>;
    }
  2. Create a new route segment for an "About" page by creating a folder app/about and a file app/about/page.js:

    JSX
    // app/about/page.js
    export default function AboutPage() {
      return <h1>About This Blog</h1>;
    }
  3. Add a shared layout to wrap both pages. Create app/layout.js (if it doesn't exist) to provide a basic navigation shell:

    JSX
    // app/layout.js
    export default function RootLayout({ children }) {
      return (
        <html lang="en">
          <body>
            <nav>My Blog Navigation</nav>
            <main>{children}</main>
          </body>
        </html>
      );
    }

When you visit /, the RootLayout renders, and your HomePage is injected into the {children} prop. When you visit /about, the same RootLayout is reused, but the AboutPage replaces the content inside the <main> tag.

Hands-on Exercise

To solidify your understanding of the App Router, perform these steps in your project:

  1. Create a new folder named contact inside app/.
  2. Add a page.js inside that folder with some text.
  3. Observe the browser at http://localhost:3000/contact. Notice how it automatically adopts the header from your RootLayout.

Common Pitfalls

  • Missing page.js: If you create a folder but forget to add a page.js file, Next.js will return a 404 for that route. Folders are just for organization unless they contain a page.js.
  • The app directory requirement: All your routing logic must live inside the app/ directory. Files placed outside (like in a src/ or pages/ folder) will not be treated as routes by the App Router.
  • Case Sensitivity: While most filesystems are case-insensitive, it is a best practice to use lowercase for all folder names to avoid deployment issues on Linux-based production servers.

Frequently Asked Questions

Q: Can I have multiple layouts? A: Yes! You can nest layout.js files inside sub-folders. This allows you to have a specific layout for your /blog section that differs from your /about section.

Q: Does every folder need a page.js? A: No. You can create folders that only serve as path segments for nested layouts without having a corresponding page at that specific URL level.

Q: What happens if I name a file index.js instead of page.js? A: Next.js will ignore it. The App Router specifically looks for page.js and layout.js as its entry points.

Recap

The App Router simplifies navigation by using the filesystem as the source of truth. By understanding that folders map to URLs and distinguishing between the specialized roles of page.js (content) and layout.js (shared shell), you've unlocked the fundamental architectural pattern of Next.js.

Up next: We'll dive into the rendering engine by exploring the difference between Server and Client Components.

Similar Posts