Back to blog

Getting Started with Next.js App Router

Learn how to build modern web applications with Next.js 14's powerful App Router and React Server Components.

Neranjana Prasad
4 min read
Next.js React Web Development

Getting Started with Next.js App Router

The Next.js App Router is a paradigm shift in how we build React applications. It introduces React Server Components, improved data fetching, and a more intuitive file-based routing system.

What is the App Router?

The App Router is Next.js’s new routing system introduced in version 13. It uses the app directory instead of the traditional pages directory, bringing several powerful features:

  • Server Components by default - Better performance and smaller bundle sizes
  • Streaming and Suspense - Progressive rendering for faster page loads
  • Simplified data fetching - No more getServerSideProps or getStaticProps
  • Layouts and Templates - Share UI across routes easily

Creating Your First Route

Creating routes in the App Router is straightforward. Each folder in the app directory represents a route segment:

// app/blog/page.tsx
export default function BlogPage() {
  return (
    <main>
      <h1>My Blog</h1>
      <p>Welcome to my blog!</p>
    </main>
  );
}

This creates a route at /blog. The page.tsx file is what makes the route publicly accessible.

Server Components vs Client Components

By default, all components in the App Router are Server Components. This means they run on the server and don’t ship JavaScript to the client.

// Server Component (default)
async function BlogPosts() {
  const posts = await fetchPosts(); // Runs on server
  
  return (
    <div>
      {posts.map(post => (
        <article key={post.id}>
          <h2>{post.title}</h2>
        </article>
      ))}
    </div>
  );
}

When you need interactivity, use the "use client" directive:

"use client";

import { useState } from "react";

export function Counter() {
  const [count, setCount] = useState(0);
  
  return (
    <button onClick={() => setCount(count + 1)}>
      Count: {count}
    </button>
  );
}

Data Fetching Made Simple

No more getServerSideProps! Just use async/await directly in your components:

async function BlogPost({ params }: { params: { slug: string } }) {
  const post = await fetch(`https://api.example.com/posts/${params.slug}`)
    .then(res => res.json());
  
  return (
    <article>
      <h1>{post.title}</h1>
      <p>{post.content}</p>
    </article>
  );
}

Layouts for Shared UI

Layouts let you share UI across multiple pages:

// app/blog/layout.tsx
export default function BlogLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <div>
      <nav>
        <a href="/blog">All Posts</a>
      </nav>
      <main>{children}</main>
      <footer>© 2024 My Blog</footer>
    </div>
  );
}

This layout wraps all pages under /blog/*.

Loading and Error States

The App Router provides special files for handling loading and error states:

// app/blog/loading.tsx
export default function Loading() {
  return <div>Loading blog posts...</div>;
}

// app/blog/error.tsx
"use client";

export default function Error({
  error,
  reset,
}: {
  error: Error;
  reset: () => void;
}) {
  return (
    <div>
      <h2>Something went wrong!</h2>
      <button onClick={reset}>Try again</button>
    </div>
  );
}

Metadata for SEO

Generate metadata for each page easily:

import type { Metadata } from "next";

export const metadata: Metadata = {
  title: "My Blog",
  description: "A blog about web development",
};

export default function BlogPage() {
  return <div>...</div>;
}

Best Practices

  1. Keep Server Components as default - Only use "use client" when needed
  2. Fetch data close to where it’s used - No prop drilling required
  3. Use loading.tsx for better UX - Show loading states automatically
  4. Leverage route groups - Organize routes without affecting URLs
  5. Optimize images - Use Next.js Image component for automatic optimization

Conclusion

The App Router represents the future of Next.js development. While there’s a learning curve, the benefits of Server Components, simplified data fetching, and improved performance make it worth the transition.

Start small, experiment with the new patterns, and gradually migrate your existing applications. The Next.js team has done an excellent job making this transition as smooth as possible.

Happy coding! 🚀


Resources: