DEV Community

Cover image for Next.js App Router Complete Beginner Guide 2026
Safdar Ali
Safdar Ali

Posted on • Originally published at safdarali.in

Next.js App Router Complete Beginner Guide 2026

The nextjs app router tutorial gap is real: official docs are reference-heavy, and beginners still think in Pages Router (pages/index.tsx). App Router uses folders in app/ where the file name tells Next.js what to do. I migrated client sites in 2024–2025 and teach this sequence on my YouTube channel. Follow these steps in order — layout, page, loading, then server fetch.

Mental model — folders are routes

Every folder under app/ maps to a URL segment. Special files: page.tsx = UI, layout.tsx = shared shell, loading.tsx = skeleton while slow segments load.

app/
layout.tsx → wraps ALL routes
page.tsx → URL: /
about/
page.tsx → URL: /about
blog/
page.tsx → URL: /blog
[slug]/
page.tsx → URL: /blog/my-post

No React Router install. Rename a folder, you rename a route. That is the core App Router win.

If you are coming from Create React App, delete the mental model of a single App.tsx with a Switch. You will have multiple layout.tsx files at different depths — root for html/body, nested for dashboard sidebars. Each layout wraps only its subtree.

Step 1 — Root layout (HTML shell once)

// app/layout.tsx
import type { Metadata } from "next";
import "./globals.css";

export const metadata: Metadata = {
title: "My App",
description: "Beginner App Router site",
};

export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body className="min-h-screen bg-white text-neutral-900">
<header className="border-b p-4">My Site</header>
<main>{children}</main>
</body>
</html>
);
}

Layouts do not remount when navigating between child pages — perfect for nav bars and fonts. Keep providers that must persist here (theme, analytics).

Step 2 — First page

// app/page.tsx — home route
export default function HomePage() {
return (
<section className="p-8">
<h1 className="text-3xl font-bold">Welcome</h1>
<p>Your first App Router page — no use client needed.</p>
</section>
);
}

Default export must be a component. This is a Server Component unless you add "use client" at the top.

Step 3 — loading.tsx for perceived speed

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

Next.js wraps the segment in Suspense automatically. Users see skeletons instead of frozen UI — critical on Indian mobile networks.

Step 4 — Server Component fetch (no useEffect)

// app/blog/page.tsx
type Post = { slug: string; title: string };

async function getPosts(): Promise<Post[]> {
const res = await fetch("https://api.example.com/posts", {
next: { revalidate: 3600 },
});
if (!res.ok) throw new Error("Failed to load posts");
return res.json();
}

export default async function BlogPage() {
const posts = await getPosts();
return (
<ul className="space-y-2 p-8">
{posts.map((post) => (
<li key={post.slug}>
<a href={"/blog/" + post.slug}>{post.title}</a>
</li>
))}
</ul>
);
}

// BEFORE — Pages Router habit (client fetch)
"use client";
useEffect(() => fetch("/api/posts").then(/* ... */), []);

// AFTER — async server component
// Data ready before HTML ships — better SEO and LCP

Deeper caching rules: SSR vs SSG vs ISR. Performance tuning: 60% load time case study.

App Router files — quick comparison table

File Purpose Required?
layout.tsx Shared UI wrapper Root required
page.tsx Route UI Yes per route
loading.tsx Loading skeleton Optional
error.tsx Error boundary Optional
not-found.tsx 404 UI Optional
route.ts API endpoint Optional

Step 5 — Add client components only as leaves

// components/CounterButton.tsx
"use client";
import { useState } from "react";

export function CounterButton() {
const [n, setN] = useState(0);
return <button onClick={() => setN(n + 1)}>Clicked {n} times</button>;
}

// app/page.tsx — server page imports client leaf
import { CounterButton } from "@/components/CounterButton";

export default function HomePage() {
return (
<section>
<h1>Home</h1>
<CounterButton />
</section>
);
}

Read RSC vs client components before marking whole pages as client — that is the beginner mistake that balloons bundle size.

Step 6 — Dynamic routes and params

// app/blog/[slug]/page.tsx
type Props = { params: Promise<{ slug: string }> };

export default async function PostPage({ params }: Props) {
const { slug } = await params;
const post = await getPost(slug);
if (!post) return <p>Not found</p>;
return <article><h1>{post.title}</h1></article>;
}

In Next.js 15, params is a Promise — await it. TypeScript strict mode helps catch forgotten awaits — strict mode guide.

Learning path after this guide

Week 1: layouts + pages + loading. Week 2: server fetch + one dynamic route. Week 3: one client form with Server Action. Week 4: deploy to Vercel and run Lighthouse. If you are choosing between stacks first, read Next.js vs React. Organise folders early with project structure guide.

For AI-assisted coding, see Cursor + Claude workflow — but build this hello-world tree by hand once so file conventions stick.

My production setup

In production I scaffold with root layout, route groups for marketing vs app, loading.tsx on slow segments, and async server pages for public content. This portfolio follows the same pattern — thin app/blog/.../page.tsx files, heavy logic elsewhere.

At my day job, beginners who complete these six steps ship their first internal page in a week — faster than learning Pages Router and relearning later.

The single takeaway

App Router = folders + special files. Layout once, page per route, loading for UX, async server fetch for data. Client components are seasoning, not the main dish.

Related: React 19 features. Contact.

If this helped you

I publish free tutorials and write-ups like this in my spare time — no paywall on the guides. If it saved you an afternoon of trial and error, you can support the work:

More guides on safdarali.in — same author, production-focused.

Top comments (0)