Next.js Basics
Master the official Next.js App Router: nested layouts and pages, Server vs Client Component boundaries, async data fetching, streaming with loading.tsx, error handling, and SEO metadata.
From React Library to Next.js Framework
While React is a UI library focused on building interactive component trees, production web applications require much more: routing, server-side rendering (SSR), image optimization, automatic code splitting, and backend data access.
Next.js is the official full-stack framework created by Vercel for React. The modern standard is the App Router (introduced in Next.js 13+), built natively on React Server Components.
The App Router Architecture
In the App Router, your directory structure directly defines your application's URL paths. Files are organized inside the app/ folder:
Folders define route segments (e.g. app/blog/), while special file names (page.tsx, layout.tsx, loading.tsx, error.tsx) define the UI and behavior for that segment.
Layouts (layout.tsx) & Pages (page.tsx)
layout.tsx
Wraps child pages with common UI (Navbars, Footers, Sidebars). Preserves state across route transitions without re-rendering.
page.tsx
The unique UI for that specific URL route. Only folders containing a page.tsx file are publicly addressable in the browser.
Client Navigation with <Link />
Never use standard HTML <a href="..."> tags for internal navigation. Use Next.js's <Link> component for instant client-side transitions and automatic background prefetching:
import Link from 'next/link';
export function Navbar() {
return (
<nav>
<Link href="/">Home</Link>
<Link href="/about">About</Link>
<Link href="/dashboard">Dashboard</Link>
</nav>
);
}Server Components vs. Client Components ("use client")
Next.js App Router components are React Server Components (RSC) by default. They execute exclusively on the server, sending pre-rendered HTML to the browser with zero client JavaScript bundle impact.
Zero Bundle & Secure
Direct database queries, access to private API keys and environment variables, fast initial page load.
- async / await directly in component
- Zero JavaScript sent to client
- No useState, useEffect, or onClick
Interactive & Stateful
Placed at the leaves of your component tree to handle interactive UI elements, state, and browser APIs.
- useState, useReducer, useEffect
- onClick, onChange, onSubmit
- Browser APIs (window, localStorage)
Async Data Fetching in Server Components
Forget useEffect boilerplate. In Server Components, simply make your component an async function:
export default async function ProductsPage() {
const res = await fetch('https://api.example.com/products', {
next: { revalidate: 3600 } // ISR: Revalidates every 1 hour
});
const products = await res.json();
return (
<div>
<h2>Products Catalog</h2>
<ul>
{products.map((p: any) => (
<li key={p.id}>{p.name} - ${p.price}</li>
))}
</ul>
</div>
);
}Loading (loading.tsx) & Error Handling (error.tsx)
loading.tsx
Automatically wraps the route inside a <Suspense fallback={<Loading />}>. Shows skeleton loaders while server data is streamed to the browser.
error.tsx ("use client")
Wraps the route in an Error Boundary. Catches unexpected runtime exceptions and provides a reset() button to retry.
Static & Dynamic SEO Metadata
import { Metadata } from 'next';
// Static Metadata Configuration
export const metadata: Metadata = {
title: 'Dashboard | SaaS Platform',
description: 'Manage your cloud infrastructure with real-time metrics.',
openGraph: {
images: ['/og-dashboard.png'],
},
};Next.js App Router Best Practices
- Keep components as Server Components by default.
- Push the
"use client"boundary down to leaf components (e.g. an interactive button or search input). - Always use
<Link>instead of<a>for fast client transitions. - Use
loading.tsxfor instant navigation feedback instead of blocking the screen. - Never mix Pages Router conventions (e.g.
getServerSideProps) in the modernapp/directory.
🔥 Live Interactive — Next.js App Structure Explorer
Click files in the visual directory tree to inspect how Next.js maps file paths to live URL routes and UI layers.
export const metadata = {
title: 'My Next.js Application',
description: 'Built with Next.js App Router'
};
export default function RootLayout({
children
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body>
<Navbar />
<main>{children}</main>
</body>
</html>
);
}Architectural Role: Root Layout: Defines global <html>, <body>, global fonts, navbar, and providers. Wraps every page in the app.
Test your mental model: Decide if each component belongs on the Server or needs the client boundary.
Component with an <input /> using useState(query) and an onChange listener to filter products live.
Fetches product inventory from a PostgreSQL database and renders a list of HTML product cards.
Reads localStorage and toggles the dark/light theme class on document.body upon button click.
Renders copyright text and standard Next.js <Link /> tags to Privacy and Terms pages.