Guide · Next.js · App Router

Next.js 14 App Router: Complete Guide for Beginners

Everything you need to know about the Next.js App Router — layouts, loading states, error boundaries, server components, and data fetching patterns explained clearly.

JS

Jatinder Sandhu

Published 1 July 2026 · 11 min read

When Next.js 13 shipped the App Router, it changed how developers think about building React applications. Routing, data fetching, layouts, and loading states all moved into a single, folder-based system built on React Server Components. By Next.js 14, the App Router became the recommended default for every new project.

If you are still on the older Pages Router, or you are new to Next.js entirely, the App Router can feel unfamiliar at first — new file conventions, a new mental model for client vs. server code, and new patterns for fetching data. This guide walks through everything you need to know, in the order you will actually use it on a real project.

I build production Next.js applications for clients regularly, and the App Router is what I reach for on every new build today. This guide is the explanation I wish I had when I started.

File-Based Routing in the App Router

Every route in the App Router lives inside the src/app directory. A folder becomes a URL segment, and a special page.tsx file inside that folder makes the route publicly accessible.

app/ page.tsx → / about/ page.tsx → /about blog/ page.tsx → /blog [slug]/ page.tsx → /blog/my-post dashboard/ layout.tsx → shared UI for all dashboard routes page.tsx → /dashboard settings/ page.tsx → /dashboard/settings

Dynamic segments use square brackets — [slug] — and the value is available to your page as a prop. This is exactly how a page like this blog post is generated.

Layouts: Shared UI That Persists

A layout.tsx file wraps every page inside its folder and any nested folders. Layouts do not re-render when you navigate between pages that share them, which makes them ideal for navigation bars, sidebars, and anything that should stay mounted — like an open modal or a persisted scroll position.

// app/dashboard/layout.tsx export default function DashboardLayout({ children, }: { children: React.ReactNode; }) { return ( <div className="flex"> <Sidebar /> <main className="flex-1">{children}</main> </div> ); }

You can nest layouts as deep as you need. The root app/layout.tsx is required in every project — it defines your <html> and <body> tags and is the right place for global fonts, providers, and analytics scripts.

Loading States with loading.tsx

Drop a loading.tsx file next to any page.tsx and Next.js automatically wraps that route in a React Suspense boundary. While the page is fetching its data on the server, your loading UI shows instantly — no manual state management required.

// app/dashboard/loading.tsx export default function Loading() { return <div className="animate-pulse">Loading dashboard...</div>; }

Why it matters

Users see instant feedback on navigation instead of a blank white screen while the server fetches data.

Scope

A loading.tsx file only affects the segment it sits in and everything nested below it.

Error Boundaries with error.tsx

An error.tsx file catches runtime errors inside its route segment and renders a fallback UI instead of crashing the whole app. It must be a Client Component because it uses React state to reset the boundary.

// app/dashboard/error.tsx 'use client'; export default function Error({ error, reset, }: { error: Error & { digest?: string }; reset: () => void; }) { return ( <div className="p-6 text-center"> <p>Something went wrong.</p> <button onClick={() => reset()} className="mt-3 underline"> Try again </button> </div> ); }

For errors thrown in the root layout itself, use a special global-error.tsx file, since the regular error boundary cannot catch failures above it in the tree.

Server Components vs. Client Components

Every component in the App Router is a Server Component by default. Server Components render on the server, send zero JavaScript to the browser, and can talk to a database or read a file system directly. Add 'use client' at the top of a file only when you need interactivity — state, effects, event handlers, or browser-only APIs.

CapabilityServer ComponentClient Component
Fetch data directly (DB, filesystem)YesNo
useState / useEffectNoYes
Ships JavaScript to browserNoYes
onClick, onChange handlersNoYes

A good rule of thumb: keep as much of your tree as Server Components as possible, and push 'use client' as far down the component tree as you can — often onto a single button or form, not an entire page.

Data Fetching Patterns

Because Server Components run on the server, you can fetch data with a plain async function — no useEffect, no client-side loading spinner logic.

// app/blog/page.tsx async function getPosts() { const res = await fetch('https://api.example.com/posts', { next: { revalidate: 3600 }, // ISR: revalidate every hour }); return res.json(); } export default async function BlogPage() { const posts = await getPosts(); return ( <ul> {posts.map((post: { id: string; title: string }) => ( <li key={post.id}>{post.title}</li> ))} </ul> ); }

The fetch caching options control your rendering strategy:

  • Default (cache: 'force-cache'): static rendering — fetched once at build time.
  • cache: 'no-store': dynamic rendering — fetched fresh on every request.
  • next: { revalidate: N }: Incremental Static Regeneration — cached, then revalidated every N seconds.

For mutations — form submissions, creating a record, sending a message — use Server Actions instead of building a separate API route. A Server Action is an async function marked with 'use server' that you can call directly from a form or a Client Component.

Common Mistakes Beginners Make

Marking entire pages 'use client'

This throws away all the server-rendering benefits. Keep the client boundary as small as possible.

Fetching data in useEffect

This causes a client-side waterfall. Fetch in a Server Component instead and pass data down as props.

Forgetting loading.tsx exists

Developers build manual spinners with useState when a single file would handle it automatically.

Mixing Pages Router and App Router patterns

getServerSideProps and getStaticProps do not exist in the App Router — use async Server Components instead.

Frequently Asked Questions

Is the App Router replacing the Pages Router?

Yes. The App Router is the recommended approach for all new Next.js projects starting with Next.js 13+, and it is the default in Next.js 14 and 15.

Do I need to rewrite my whole app to migrate?

No. Next.js supports incremental adoption — you can run the app/ and pages/ directories side by side and migrate route by route.

Can Server Components use hooks like useState?

No. Hooks only work in Client Components marked with the ‘use client’ directive at the top of the file.

How is this different from getServerSideProps?

Server Components replace that pattern entirely — you just write an async function and await your data directly in the component.

Conclusion

The App Router is not just a new set of file conventions — it is a genuinely different way to build React apps, with Server Components at the center. Once the folder structure, layouts, loading states, and Server/Client boundary click, most developers find it faster to build with than the old Pages Router.

Start small: convert one route, get comfortable with async Server Components, then move on to Server Actions for your forms. I use this exact stack — Next.js App Router, Server Components, and Server Actions — on every client project I build today, and it consistently produces faster, more maintainable applications.

Need help migrating your app to the App Router, or want a Next.js project built the right way from day one? Get in touchand let's talk about your project.

ShareXLinkedIn

About the Author

Hi, I'm Jatinder Sandhu, a Full-Stack Developer with 6+ years of experience building websites, web applications, business management systems, and AI-powered solutions using technologies like Next.js, React, Node.js, and MongoDB.

I share practical technology guides, development tutorials, and business growth insights based on real-world experience working on client projects.

If you're looking to build a website, custom software, business automation system, or AI-powered solution, explore my portfolio at jatinder.malwaland.com.