Books/React & Next.js Essentials/Next.js Routing and Pages

    Next.js Routing and Pages

    Next.js Routing and Pages

    Next.js is a React framework that adds powerful features on top of React, and its most distinctive feature is file-based routing. Instead of configuring routes in code, you create files and folders — each one automatically becomes a page in your app.

    App Router vs Pages Router

    Next.js has two routing systems:

    App RouterPages Router
    Directoryapp/pages/
    ReleasedNext.js 13+ (2023)Original
    StatusRecommendedStill supported
    ComponentsServer Components by defaultClient Components by default

    The App Router is the modern standard. AI tools generate App Router code by default. This tutorial focuses entirely on the App Router.

    File-Based Routing Basics

    In Next.js, the file structure inside the app/ directory determines your URLs:

    app/
    ├── page.tsx              → /
    ├── about/
    │   └── page.tsx          → /about
    ├── contact/
    │   └── page.tsx          → /contact
    ├── blog/
    │   ├── page.tsx          → /blog
    │   └── [slug]/
    │       └── page.tsx      → /blog/my-first-post
    └── dashboard/
        ├── page.tsx          → /dashboard
        ├── settings/
        │   └── page.tsx      → /dashboard/settings
        └── profile/
            └── page.tsx      → /dashboard/profile
    

    The key file is page.tsx — it defines the content for that route. Every folder with a page.tsx file becomes a URL in your app.

    A Basic Page

    // app/page.tsx — this is the home page (/)
    export default function HomePage() {
      return (
        <main>
          <h1>Welcome to My App</h1>
          <p>This is the home page.</p>
        </main>
      );
    }
    // app/about/page.tsx — this is /about
    export default function AboutPage() {
      return (
        <main>
          <h1>About Us</h1>
          <p>Learn more about our team.</p>
        </main>
      );
    }

    Notice: the function name doesn't determine the URL — only the file path does.

    What to ask your AI: "Create a new page at /[path] in my Next.js app. It should display [content]."

    Dynamic Routes with [slug]

    Square brackets create dynamic routes — pages that match different URLs:

    // app/blog/[slug]/page.tsx — matches /blog/anything
    
    interface BlogPostPageProps {
      params: Promise<{ slug: string }>;
    }
    
    export default async function BlogPostPage({ params }: BlogPostPageProps) {
      const { slug } = await params;
    
      // Fetch the blog post using the slug
      const post = await fetch(`https://api.example.com/posts/${slug}`).then(
        res => res.json()
      );
    
      return (
        <article>
          <h1>{post.title}</h1>
          <p>{post.content}</p>
        </article>
      );
    }

    The params object contains the dynamic segments:

    File PathURLparams
    app/blog/[slug]/page.tsx/blog/hello-world{ slug: "hello-world" }
    app/users/[id]/page.tsx/users/42{ id: "42" }
    app/shop/[category]/[id]/page.tsx/shop/shoes/123{ category: "shoes", id: "123" }

    What to ask your AI: "Create a dynamic route for /products/[id] that fetches and displays a single product."

    Layouts — Shared UI

    Layouts wrap pages with shared UI like headers, sidebars, and footers. They persist across page navigations:

    // app/layout.tsx — the root layout (wraps every page)
    import { ReactNode } from "react";
    
    export default function RootLayout({ children }: { children: ReactNode }) {
      return (
        <html lang="en">
          <body>
            <header>
              <nav>
                <a href="/">Home</a>
                <a href="/about">About</a>
                <a href="/blog">Blog</a>
              </nav>
            </header>
            <main>{children}</main>
            <footer>
              <p>My App 2025</p>
            </footer>
          </body>
        </html>
      );
    }

    Nested Layouts

    You can have layouts at any level — they nest automatically:

    // app/dashboard/layout.tsx — wraps all /dashboard/* pages
    import { ReactNode } from "react";
    
    export default function DashboardLayout({ children }: { children: ReactNode }) {
      return (
        <div className="flex">
          <aside className="w-64 bg-gray-100 p-4">
            <h2>Dashboard</h2>
            <nav>
              <a href="/dashboard">Overview</a>
              <a href="/dashboard/settings">Settings</a>
              <a href="/dashboard/profile">Profile</a>
            </nav>
          </aside>
          <div className="flex-1 p-6">
            {children}
          </div>
        </div>
      );
    }

    Now every page under /dashboard/* gets the sidebar automatically. The {children} placeholder is where the page content renders.

    What to ask your AI: "Create a dashboard layout with a sidebar navigation and a main content area. Include links to [these pages]."

    Loading States

    Next.js has built-in loading UI support. Create a loading.tsx file and it shows automatically while the page is loading:

    // app/blog/loading.tsx — shows while /blog page loads
    export default function BlogLoading() {
      return (
        <div className="animate-pulse space-y-4">
          <div className="h-8 bg-gray-200 rounded w-1/3"></div>
          <div className="h-4 bg-gray-200 rounded w-full"></div>
          <div className="h-4 bg-gray-200 rounded w-2/3"></div>
        </div>
      );
    }

    This loading component displays automatically while the page.tsx in the same directory is fetching data.

    Error Handling

    Similarly, create error.tsx to handle errors:

    // app/blog/error.tsx
    "use client"; // Error components must be Client Components
    
    export default function BlogError({
      error,
      reset,
    }: {
      error: Error;
      reset: () => void;
    }) {
      return (
        <div className="text-center py-10">
          <h2 className="text-2xl font-bold text-red-600">Something went wrong!</h2>
          <p className="text-gray-600 mt-2">{error.message}</p>
          <button
            onClick={reset}
            className="mt-4 px-4 py-2 bg-blue-500 text-white rounded"
          >
            Try again
          </button>
        </div>
      );
    }

    The Link Component — Client-Side Navigation

    Use Next.js Link component instead of regular <a> tags for navigation between pages:

    import Link from "next/link";
    
    function Navigation() {
      return (
        <nav className="flex gap-4">
          <Link href="/">Home</Link>
          <Link href="/about">About</Link>
          <Link href="/blog">Blog</Link>
          <Link href="/blog/my-first-post">First Post</Link>
          <Link
            href="/dashboard"
            className="text-blue-500 hover:underline"
          >
            Dashboard
          </Link>
        </nav>
      );
    }

    Why use Link instead of <a>:

    • Client-side navigation — no full page reload, instant transitions
    • Prefetching — Next.js preloads linked pages in the background
    • Preserves state — React state is maintained during navigation

    Programmatic Navigation

    Sometimes you need to navigate in code (e.g., after a form submission):

    "use client";
    
    import { useRouter } from "next/navigation";
    
    function LoginForm() {
      const router = useRouter();
    
      const handleSubmit = async (e: React.FormEvent) => {
        e.preventDefault();
        // ... login logic
        router.push("/dashboard"); // Navigate programmatically
      };
    
      return <form onSubmit={handleSubmit}>...</form>;
    }

    Special Files Summary

    Next.js uses special file names for different purposes:

    FilePurpose
    page.tsxThe page content for that route
    layout.tsxShared wrapper that persists across navigations
    loading.tsxLoading UI shown while page is loading
    error.tsxError UI shown when something fails
    not-found.tsx404 page for that route segment
    template.tsxLike layout, but re-mounts on every navigation

    What to ask your AI: "Set up the file structure for a Next.js app with [these pages]. Include layouts for [these sections] and loading states."

    What's Next?

    You understand routing and page structure. The next tutorial covers Data Fetching in Next.js — how to load data in server components and client components.


    🌐 www.genai-mentor.ai