К основному содержанию
скилл CX Codex

nextjs-server-navigation — скилл для Claude Code: установка

Учит ИИ-агента настраивать навигацию в серверных компонентах Next.js через <Link> и redirect() без необоснованного добавления директивы 'use client'.

Установить в Claude Code · Через Skills CLI (Vercel) Все способы и платформы ↓
npx skills add wsimmonds/claude-nextjs-skills --skill nextjs-server-navigation -a claude-code
Открыть на GitHub

Что делает nextjs-server-navigation

Модели часто ошибаются в коде Next.js: видя задачу сделать ссылку или переход, они по привычке превращают файл в клиентский и вызывают хук useRouter(). Этот скилл запрещает клиентские хуки внутри Server Components. Он объясняет агенту, когда использовать стандартный <Link> из next/link, а когда серверный redirect() из next/navigation.

Инструкции скилла охватывают проверку сессий через cookies() и перенаправления внутри Server Actions при отправке форм. В серверных компонентах нельзя вешать onClick, поэтому попытка внедрить обработчик клика ломает серверный рендеринг. Правило также требует явной типизации событий в клиентских компонентах и запрещает использовать тип any.

Какие задачи решает

  • настроить ссылки через <Link> в серверных компонентах Next.js
  • сделать редирект неавторизованных пользователей по данным из cookies()
  • перенаправить пользователя после выполнения Server Action в форме
  • исключить ошибочное добавление 'use client' при создании навигации

Примеры запросов агенту

  • Сделай серверный компонент страницы профиля с проверкой куки и редиректом на /login.
  • Добавь список ссылок на товары в серверный компонент каталога без перевода файла в клиентский.
  • Создай серверное действие для выхода из системы с перенаправлением на главную страницу.

Как установить nextjs-server-navigation

1Через Skills CLI (Vercel)

npx skills add wsimmonds/claude-nextjs-skills --skill nextjs-server-navigation -a claude-code

2Вручную: положить файлы

~/.claude/skills/nextjs-server-navigation/SKILL.md

Папка скилла целиком; для одного проекта — .claude/skills/nextjs-server-navigation/

По шагам, с командами для каждой платформы: Как установить скилл в Claude Code: пять способов

Вопросы о nextjs-server-navigation

Как установить nextjs-server-navigation в Claude Code?

Выполните команду npx skills add wsimmonds/claude-nextjs-skills --skill nextjs-server-navigation -a claude-code.

Зачем нужен этот скилл?

Он удерживает ассистента от добавления 'use client' только ради ссылок и блокирует вызовы хука useRouter() там, где достаточно <Link> или redirect().

Можно ли вызывать useRouter() в серверных компонентах?

Нет. Хук useRouter() работает исключительно в клиентских компонентах с директивой 'use client'. Для Server Components подходят только <Link> или функция redirect().

Исходный текст

SKILL.md · MIT
---
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:**
```typescript
// app/page.tsx (Server Component - NO 'use client'!)
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:**
```typescript
// app/page.tsx
'use client';  // ❌ NO! Server components don't need this for navigation!

import { useRouter } from 'next/navigation';  // ❌ Wrong for server components

export default function Page() {
  const router = useRouter();  // ❌ This is client-side navigation
  // ...
}
```

## Server Navigation Methods

### Method 1: Link Component (Recommended for Links)

```typescript
// app/page.tsx
import Link from 'next/link';

export default async function Page() {
  // Can still fetch data - this is a server component!
  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)

```typescript
// app/profile/page.tsx
import { redirect } from 'next/navigation';
import { cookies } from 'next/headers';

export default async function ProfilePage() {
  // Check authentication
  const cookieStore = await cookies();
  const session = cookieStore.get('session');

  // Redirect if not authenticated
  if (!session) {
    redirect('/login');
  }

  // Fetch user data
  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

```typescript
// app/page.tsx
import { logout } from './actions';

export default async function Page() {
  return (
    <div>
      <h1>Dashboard</h1>

      <form action={logout}>
        <button type="submit">Logout</button>
      </form>
    </div>
  );
}

// app/actions.ts
'use server';

import { redirect } from 'next/navigation';

export async function logout() {
  // Clear session
  await clearSession();

  // Redirect to login page
  redirect('/login');
}
```

## Complete Example: Navigation Patterns

```typescript
// app/page.tsx - Demonstrates multiple navigation patterns

import Link from 'next/link';
import { redirect } from 'next/navigation';
import { headers } from 'next/headers';

export default async function HomePage() {
  // Server-side logic
  const headersList = await headers();
  const userAgent = headersList.get('user-agent');

  // Conditional redirect example
  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

```typescript
// ❌ WRONG
function handleClick(e: any) { ... }

// ✅ CORRECT - Not needed in server components!
// Server components don't have onClick handlers

// For client components with handlers:
'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

```typescript
// ❌ WRONG
'use client';  // Don't add this just for navigation!

import Link from 'next/link';

export default function Page() {
  return <Link href="/about">About</Link>;
}
```

```typescript
// ✅ CORRECT
import Link from 'next/link';

// No 'use client' needed!
export default async function Page() {
  return <Link href="/about">About</Link>;
}
```

### ❌ Mistake 2: Using useRouter() in Server Component

```typescript
// ❌ WRONG
import { useRouter } from 'next/navigation';  // This is for CLIENT components!

export default async function Page() {
  const router = useRouter();  // ERROR! Can't use hooks in server components
  // ...
}
```

```typescript
// ✅ CORRECT - Use Link or redirect()
import Link from 'next/link';
import { redirect } from 'next/navigation';

export default async function Page() {
  // Conditional redirect
  const shouldRedirect = await checkSomething();
  if (shouldRedirect) {
    redirect('/other-page');
  }

  // Or navigation links
  return <Link href="/other-page">Go</Link>;
}
```

### ❌ Mistake 3: Making Component Client-Side for Simple Navigation

```typescript
// ❌ WRONG - Loses server component benefits!
'use client';

export default function Page() {
  return (
    <div>
      <Link href="/dashboard">Dashboard</Link>
    </div>
  );
}
```

```typescript
// ✅ CORRECT - Keep it as a server component!
export default async function Page() {
  // Can now fetch data server-side
  const data = await fetchData();

  return (
    <div>
      <Link href="/dashboard">Dashboard</Link>
      <p>{data.message}</p>
    </div>
  );
}
```

## Advanced Patterns

### Programmatic Navigation in Server Actions

```typescript
// app/page.tsx
import { createPost } from './actions';

export default async function Page() {
  return (
    <form action={createPost}>
      <input name="title" required />
      <button type="submit">Create Post</button>
    </form>
  );
}

// app/actions.ts
'use server';

import { redirect } from 'next/navigation';

export async function createPost(formData: FormData) {
  const title = formData.get('title') as string;

  // Save to database
  const post = await db.posts.create({ title });

  // Redirect to the new post
  redirect(`/posts/${post.id}`);
}
```

### Multiple Links in Server Component

```typescript
// app/page.tsx
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":

- [ ] Create a server component (no 'use client')
- [ ] Import `Link` from 'next/link'
- [ ] Add `<Link>` components with href prop
- [ ] Keep component as `async` if fetching data
- [ ] Do NOT import useRouter from next/navigation
- [ ] Do NOT add 'use client' directive
- [ ] Use proper TypeScript types (no `any`)

## 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!**

© wsimmonds · MIT · wsimmonds/claude-nextjs-skills

Похожие скиллы

Всё по теме «Фронтенд и UI» →
frontend-design официальный anthropics Скилл задаёт осмысленное визуальное направление для новых интерфейсов и редизайна. Подойдёт, когда стандартный шаблонный UI не устраивает. 1 025 790установок design-taste-frontend Leonxlnx Скилл задаёт арт-дирекцию для публичных страниц и рабочих экранов, а затем проверяет результат в браузере по скриншотам. Нужен, когда интерфейс выглядит шаблонным или недоработанным. CX Codex +1 678 700установок prototype Matt Pocock Создаёт временный прототип, чтобы проверить логику, модель состояния или вид интерфейса до работы над основным кодом. 986 201установок hyperframes heygen-com Скилл задаёт агенту правила рендера HTML-кода в видео через HyperFrames. Помогает собирать проморолики, эксплейнеры и титры прямо в коде проекта. CX Codex +1 1 200 000установок hyperframes-cli heygen-com Управляет проектами HyperFrames через терминал: собирает таймлайн, проверяет контраст кадров, запускает предпросмотр и рендерит видео локально или в облаке. CX Codex +1 1 300 000установок webapp-testing официальный anthropics Скилл запускает проверки локальных веб-приложений через Playwright: помогает отлаживать UI, делать скриншоты и смотреть логи браузера. 186 758установок

Из того же набора8

nextjs-app-router-fundamentals Скилл ведёт агента по Next.js App Router: перенос с Pages Router, вложенные layout, метаданные, динамические маршруты. Пригодится при переходе на app/. CX Codex +1 2 200установок nextjs-server-client-components Помогает выбрать между Server и Client Components в Next.js App Router, настроить чтение cookies, работу с searchParams и избежать смешивания клиентских и серверных API. CX Codex +1 360установок vercel-ai-sdk Подсказывает агенту, как писать код на Vercel AI SDK v5: чат через useChat, стриминг, вызов инструментов, эмбеддинги. CX Codex +1 337установок nextjs-advanced-routing Скилл для ИИ-агента, который разбирает продвинутый App Router в Next.js: серверные экшены, Route Handlers, параллельные и перехватывающие маршруты. CX Codex +1 334установок nextjs-client-cookie-pattern Скилл показывает, как из клиентского компонента Next.js выставить серверную куку через server action. Пригодится для тем, авторизации и языковых настроек. CX Codex +1 323установок nextjs-use-search-params-suspense Скилл объясняет, как правильно читать параметры URL в клиентских компонентах Next.js: директива 'use client' плюс обёртка Suspense. CX Codex +1 311установок nextjs-dynamic-routes-params Скилл подсказывает агенту, как строить динамические сегменты App Router и читать params в Next.js 15+. Пригодится, когда страницы зависят от ID или слага из URL. CX Codex +1 303установок

Спонсоры проекта

Компании, которые помогают держать аналитику открытой