Web Dev Notes
Master Next.js routing — file-based routing conventions, App Router architecture, dynamic routes, route groups, parallel routes, and server components.
Introduction
Next.js revolutionized React routing by replacing manual route configuration with a file-based system. Instead of writing route definitions in code, you simply create files and folders — the file system IS the router. With Next.js 13+, the App Router introduced a new paradigm built on React Server Components, nested layouts, and streaming, making routing even more powerful.
This guide covers the App Router architecture, file conventions, dynamic routing, route groups, parallel routes, and how server components change the way we think about data fetching in routes.
File-Based Routing Fundamentals
In Next.js, the folder structure inside app/ directly maps to URL paths. Each folder represents a route segment, and special files define the UI for that segment.
| ├── page.tsx | / |
| │ └── page.tsx | /about |
| │ ├── page.tsx | /blog |
| │ └── page.tsx | /blog/hello-world, /blog/nextjs-routing |
| │ ├── layout.tsx | Shared layout for all /dashboard/* pages |
| │ ├── page.tsx | /dashboard |
| │ │ └── page.tsx | /dashboard/settings |
| │ └── page.tsx | /dashboard/analytics |
| └── layout.tsx | Root layout (wraps entire app) |
Key principle: A route is only publicly accessible if its folder contains a page.tsx file. Folders without page.tsx are used for organization only.
Special File Conventions
The App Router uses specific filenames to define different aspects of a route:
| File | Purpose | Renders |
|---|---|---|
page.tsx | Unique UI for a route | The main page content |
layout.tsx | Shared UI that wraps children | Navigation, sidebars |
loading.tsx | Loading UI (Suspense boundary) | Skeleton/spinner |
error.tsx | Error handling UI | Error recovery |
not-found.tsx | 404 UI for this segment | Custom not-found page |
template.tsx | Like layout but re-mounts | Animations, per-page state |
default.tsx | Fallback for parallel routes | Default slot content |
Layout and Page Relationship
// app/dashboard/layout.tsx — wraps all dashboard pages
export default function DashboardLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<div className="flex">
<aside className="w-64 bg-gray-900 min-h-screen p-4">
<nav>
<a href="/dashboard">Overview</a>
<a href="/dashboard/analytics">Analytics</a>
<a href="/dashboard/settings">Settings</a>
</nav>
</aside>
<main className="flex-1 p-8">
{children} {/* page.tsx renders here */}
</main>
</div>
);
}
// app/dashboard/page.tsx — the actual /dashboard content
export default function DashboardPage() {
return (
<div>
<h1>Dashboard Overview</h1>
<p>Welcome to your dashboard!</p>
</div>
);
}Important: Layouts persist across navigations. When a user moves from /dashboard to /dashboard/analytics, the layout stays mounted (sidebar doesn't re-render), only the page.tsx content swaps.
Dynamic Routes
Dynamic segments capture variable path parameters using square brackets:
Basic Dynamic Route
Catch-All Routes
Optional Catch-All Routes
Route Groups
Route groups let you organize routes without affecting the URL path. Wrap a folder name in parentheses:
| │ ├── layout.tsx | Marketing-specific layout |
| │ │ └── page.tsx | /about (NOT /marketing/about) |
| │ └── page.tsx | /blog |
| │ ├── layout.tsx | Dashboard-specific layout (with sidebar) |
| │ │ └── page.tsx | /dashboard |
| │ └── page.tsx | /settings |
| └── layout.tsx | Root layout |
Use cases for route groups:
- Apply different layouts to different sections
- Organize code by team or feature
- Create multiple root layouts for different app sections
Server Components in Routes
By default, all components in the App Router are React Server Components. They run on the server and send HTML to the client — no JavaScript bundle shipped for them.
When to Use Client Components
Add "use client" directive when you need interactivity:
Data Fetching Patterns
Parallel Routes
Parallel routes render multiple pages simultaneously in the same layout using named slots:
| │ └── page.tsx | Renders in analytics slot |
| │ └── page.tsx | Renders in notifications slot |
| └── page.tsx | Renders in activity slot |
// app/dashboard/layout.tsx
export default function DashboardLayout({
children,
analytics,
notifications,
activity,
}: {
children: React.ReactNode;
analytics: React.ReactNode;
notifications: React.ReactNode;
activity: React.ReactNode;
}) {
return (
<div className="grid grid-cols-3 gap-4">
<div className="col-span-2">{children}</div>
<div>{notifications}</div>
<div className="col-span-2">{analytics}</div>
<div>{activity}</div>
</div>
);
}Intercepting Routes
Intercepting routes let you show a route in a modal while maintaining the full page as a shareable URL:
| │ ├── page.tsx | /feed (photo grid) |
| │ │ └── page.tsx | Intercepts /photo/[id] as modal |
| │ └── page.tsx | /photo/123 (full page view) |
Convention: (.) = same level, (..) = one level up, (...) = root level.
Navigation
Link Component
import Link from 'next/link';
export function Navigation() {
return (
<nav>
<Link href="/">Home</Link>
<Link href="/blog">Blog</Link>
<Link href={`/blog/${post.slug}`}>Read More</Link>
<Link href="/dashboard" prefetch={false}>Dashboard</Link>
</nav>
);
}Programmatic Navigation
"use client";
import { useRouter } from 'next/navigation';
export function SearchForm() {
const router = useRouter();
function handleSubmit(query: string) {
router.push(`/search?q=${query}`);
// router.replace() - replaces current history entry
// router.back() - go back
// router.refresh() - re-fetch server components
}
}Route Metadata and SEO
Static and Dynamic Rendering
// Static (default) — rendered at build time
export default async function BlogPage() {
const posts = await fetch('https://api.example.com/posts');
return <PostList posts={posts} />;
}
// Dynamic — rendered on every request
export const dynamic = 'force-dynamic';
// OR use dynamic functions:
import { cookies, headers } from 'next/headers';
export default async function ProfilePage() {
const session = cookies().get('session'); // Makes route dynamic
return <Profile userId={session.value} />;
}
// Static with revalidation (ISR)
export const revalidate = 60; // Regenerate every 60 secondsInterview Questions
Q1: How does Next.js file-based routing differ from React Router?
Answer: React Router requires manual route configuration in code (<Route path="/about" element={<About/>}/>). Next.js uses the filesystem — creating app/about/page.tsx automatically creates the /about route. Next.js also provides built-in layouts, loading states, error boundaries, and server-side rendering per route, which React Router handles through additional libraries.
Q2: What is the difference between a layout and a template in Next.js?
Answer: Both wrap child routes, but layouts persist across navigations (maintain state, don't re-mount) while templates create a new instance for each navigation. Use layouts for persistent UI like navigation bars. Use templates when you need fresh state per page (animations that should replay, per-page analytics tracking).
Q3: How do Server Components change data fetching in routes?
Answer: Server Components allow async/await directly in the component — no need for useEffect, getServerSideProps, or client-side loading states. Data is fetched on the server, HTML is sent to the client, and the component's JavaScript is never shipped to the browser. This reduces bundle size and eliminates client-side loading waterfalls.
Q4: What are parallel routes and when would you use them?
Answer: Parallel routes render multiple page components in the same layout simultaneously using named slots (@folder). Use them for dashboards where different sections load independently, modal patterns where the main page stays visible, or split views. Each slot can have independent loading/error states and can be conditionally rendered.
Quick Revision Notes
- File = Route:
app/about/page.tsx→/about - Layout persists: Stays mounted across navigations (shared UI)
- Server Components default: No client JS shipped, direct async data fetching
- Dynamic segments:
[slug]for params,[...slug]for catch-all - Route groups:
(name)organizes without affecting URL - Parallel routes:
@slotfor independent page sections - Intercepting routes:
(..)pathshows route in modal
Summary
Next.js routing eliminates configuration through filesystem conventions. The App Router builds on React Server Components to enable powerful patterns — nested layouts that persist, parallel routes that load independently, and server-first data fetching that reduces client-side JavaScript. Understanding these conventions and patterns is essential for building performant, SEO-friendly Next.js applications.
Exam Focus
Revise definitions, diagrams, examples, and short-answer points for Next.js Routing — File-Based Routing and App Router.
Interview Use
Prepare one clear explanation, one practical example, and one common mistake for this Web Development topic.
Search Terms
web-development, web development, web, development, frontend, frameworks, nextjs, routing
Related Web Development Topics