You now know how routes are created - this lesson is about moving between them. Next.js replaces the plain anchor tag with a smarter Link component that enables client-side navigation, prefetching, and preserved layout state. You will also learn programmatic navigation with useRouter and how to read the current URL.
A regular a tag triggers a full page load: the browser throws away the current page, downloads everything again, and re-runs all JavaScript. The Link component intercepts the click, fetches only the parts of the new route that changed, and swaps them in. Layouts persist, state survives, and navigation feels instant.
// app/components/Navbar.js
import Link from 'next/link';
export default function Navbar() {
return (
<nav>
<Link href='/'>Home</Link>
<Link href='/blog'>Blog</Link>
<Link href='/about'>About</Link>
<Link href={{ pathname: '/search', query: { q: 'nextjs' } }}>
Search
</Link>
</nav>
);
}Link renders a real anchor tag in the HTML, so right-click, open in new tab, and SEO crawling all still work. The href can be a string or an object with pathname and query.
In production, Next.js automatically prefetches a route when its Link scrolls into the viewport. By the time the user clicks, much of the destination is already loaded. You can opt out for rarely-used links:
<Link href='/archive' prefetch={false}>Old Archive</Link>Prefetching only happens in production builds, so do not look for it in npm run dev.
Navigation bars usually highlight the current page. Use the usePathname hook in a Client Component:
'use client';
import Link from 'next/link';
import { usePathname } from 'next/navigation';
export default function NavLink({ href, children }) {
const pathname = usePathname();
const isActive = pathname === href;
return (
<Link href={href} className={isActive ? 'active' : ''}>
{children}
</Link>
);
}The 'use client' directive is required because hooks only run in Client Components - Lesson 6 explains this boundary in depth.
Sometimes navigation happens after an action - submitting a form, finishing a login. Use the useRouter hook from next/navigation:
'use client';
import { useRouter } from 'next/navigation';
export default function LoginButton() {
const router = useRouter();
async function handleLogin() {
// ...authenticate...
router.push('/dashboard');
}
return <button onClick={handleLogin}>Log in</button>;
}Useful router methods:
Important: import from next/navigation, not the legacy next/router, when using the App Router.
Server Components cannot use hooks, but they can redirect:
import { redirect } from 'next/navigation';
export default async function ProfilePage() {
const user = await getUser();
if (!user) redirect('/login');
return <h1>Welcome, {user.name}</h1>;
}redirect throws internally, so code after it never runs - no need for a return statement.
Next up: Lesson 6 tackles the most important concept in modern Next.js - the difference between Server Components and Client Components.