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)