| name | nextjs-server-navigation |
| description | Guide for implementing navigation in Next.js Server Components using Link component and redirect() function. Covers the difference between server and client navigation methods. Use when adding links, redirects, or navigation logic in server components without converting them to client components unnecessarily. |
| allowed-tools | Read, Write, Edit, Glob, Grep, Bash |
Next.js: Server Component Navigation Pattern
⚠️ CRITICAL RULE
Server Components use DIFFERENT navigation methods than Client Components!
When requirements call for server-rendered navigation—for example, linking to other pages, redirecting after a check, or demonstrating routing patterns—prefer <Link> and redirect() within Server Components. You still avoid 'use client' unless a client-only API is involved.
The Pattern
Scenario: build a server component that demonstrates proper navigation patterns
✅ CORRECT Solution:
import Link from 'next/link';
export default async function Page() {
return (
<div>
<h1>Home</h1>
<Link href="/dashboard">Go to Dashboard</Link>
<Link href="/profile">View Profile</Link>
</div>
);
}
❌ WRONG Solution:
'use client';
import { useRouter } from 'next/navigation';
export default function Page() {
const router = useRouter();
}
Server Navigation Methods
Method 1: Link Component (Recommended for Links)
import Link from 'next/link';
export default async function Page() {
const data = await fetchData();
return (
<div>
<h1>Welcome</h1>
{/* Simple navigation link */}
<Link href="/about">About Us</Link>
{/* Dynamic link */}
<Link href={`/products/${data.productId}`}>View Product</Link>
{/* Link with styling */}
<Link href="/dashboard" className="btn-primary">
Dashboard
</Link>
</div>
);
}
Key Points:
- ✅ Works in Server Components (no 'use client' needed)
- ✅ Can be async function
- ✅ Can fetch data
- ✅ No hooks required
Method 2: redirect() Function (For Conditional Redirects)
import { redirect } from 'next/navigation';
import { cookies } from 'next/headers';
export default async function ProfilePage() {
const cookieStore = await cookies();
const session = cookieStore.get('session');
if (!session) {
redirect('/login');
}
const user = await fetchUser(session.value);
return <div>Welcome, {user.name}!</div>;
}
When to use redirect():
- Conditional redirects based on server-side data
- Authentication checks
- Permission validation
- Data-based routing
Method 3: Button with Server Action
import { logout } from './actions';
export default async function Page() {
return (
<div>
<h1>Dashboard</h1>
<form action={logout}>
<button type="submit">Logout</button>
</form>
</div>
);
}
'use server';
import { redirect } from 'next/navigation';
export async function logout() {
await clearSession();
redirect('/login');
}
Complete Example: Navigation Patterns
import Link from 'next/link';
import { redirect } from 'next/navigation';
import { headers } from 'next/headers';
export default async function HomePage() {
const headersList = await headers();
const userAgent = headersList.get('user-agent');
if (userAgent?.includes('bot')) {
redirect('/bot-page');
}
return (
<div>
<h1>Welcome to Our App</h1>
{/* Navigation Links */}
<nav>
<Link href="/about">About</Link>
<Link href="/products">Products</Link>
<Link href="/contact">Contact</Link>
</nav>
{/* Button-style link */}
<Link href="/get-started" className="button">
Get Started
</Link>
{/* Dynamic link */}
<Link href={`/user/${123}`}>View Profile</Link>
</div>
);
}
TypeScript: NEVER Use any Type
function handleClick(e: any) { ... }
'use client';
function handleClick(e: React.MouseEvent<HTMLButtonElement>) { ... }
Server vs Client Navigation Comparison
| Feature | Server Component | Client Component |
|---|
<Link> | ✅ Yes | ✅ Yes |
redirect() | ✅ Yes | ❌ No |
useRouter() | ❌ No | ✅ Yes |
usePathname() | ❌ No | ✅ Yes |
| async function | ✅ Yes | ❌ No |
| 'use client' | ❌ No | ✅ Yes |
Common Mistakes to Avoid
❌ Mistake 1: Adding 'use client' for Navigation
'use client';
import Link from 'next/link';
export default function Page() {
return <Link href="/about">About</Link>;
}
import Link from 'next/link';
export default async function Page() {
return <Link href="/about">About</Link>;
}
❌ Mistake 2: Using useRouter() in Server Component
import { useRouter } from 'next/navigation';
export default async function Page() {
const router = useRouter();
}
import Link from 'next/link';
import { redirect } from 'next/navigation';
export default async function Page() {
const shouldRedirect = await checkSomething();
if (shouldRedirect) {
redirect('/other-page');
}
return <Link href="/other-page">Go</Link>;
}
❌ Mistake 3: Making Component Client-Side for Simple Navigation
'use client';
export default function Page() {
return (
<div>
<Link href="/dashboard">Dashboard</Link>
</div>
);
}
export default async function Page() {
const data = await fetchData();
return (
<div>
<Link href="/dashboard">Dashboard</Link>
<p>{data.message}</p>
</div>
);
}
Advanced Patterns
Programmatic Navigation in Server Actions
import { createPost } from './actions';
export default async function Page() {
return (
<form action={createPost}>
<input name="title" required />
<button type="submit">Create Post</button>
</form>
);
}
'use server';
import { redirect } from 'next/navigation';
export async function createPost(formData: FormData) {
const title = formData.get('title') as string;
const post = await db.posts.create({ title });
redirect(`/posts/${post.id}`);
}
Multiple Links in Server Component
import Link from 'next/link';
export default async function NavigationPage() {
const pages = await fetchPages();
return (
<nav>
<h2>Site Navigation</h2>
<ul>
{pages.map((page) => (
<li key={page.id}>
<Link href={`/pages/${page.slug}`}>
{page.title}
</Link>
</li>
))}
</ul>
</nav>
);
}
Quick Decision Tree
Need navigation in a component?
│
├─ Is it a Server Component (no 'use client')?
│ ├─ Static link → Use <Link>
│ ├─ Conditional redirect → Use redirect()
│ └─ Form submission → Server Action with redirect()
│
└─ Is it a Client Component ('use client')?
├─ Link → Use <Link> (works in both!)
└─ Programmatic → Use useRouter()
When to Use Client-Side Navigation Instead
Use Client Components ('use client' + useRouter()) ONLY when you need:
- Programmatic navigation based on client state
- Navigation after client-side animations
- Browser-only APIs (window, localStorage)
- React hooks (useState, useEffect)
For everything else, use Server Component navigation!
Quick Checklist
When you see "demonstrates navigation patterns":
Summary
Server Component Navigation:
- ✅ Use
<Link> for navigation links
- ✅ Use
redirect() for conditional redirects
- ✅ Keep component async if needed
- ✅ No 'use client' required
- ✅ No hooks needed
This pattern is simpler and more performant than client-side navigation for static links!