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

clerk-react-router-patterns — скилл для Claude Code: установка

Помогает настроить Clerk с React Router v7/v8: загрузчики, защищённые маршруты, SSR и выбор организации. Нужен при добавлении авторизации в роутер.

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

Что делает clerk-react-router-patterns

Скилл разбирает интеграцию @clerk/react-router с React Router v7.9+ и v8. Он подсказывает, как связать clerkMiddleware() с rootAuthLoader, получать пользователя через getAuth(args) в loaders и actions, защищать маршруты редиректами и передавать данные сессии в SSR. Отдельно рассматривает клиентские хуки и OrganizationSwitcher.

Внутри есть отдельные справочные материалы по loaders и actions, защищённым маршрутам и SSR-аутентификации. Версия React Router влияет на настройку: в v7 нужен флаг future.v8_middleware, а в v8 он удалён; для v8 также требуется ssr.noExternal для @clerk/react-router в vite.config.ts. Без вызова rootAuthLoader(args) в loader файла root.tsx getAuth ломается во вложенных loaders.

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

  • настроить Clerk в React Router v7 или v8
  • получить userId и orgId в loader или action
  • закрыть маршрут редиректом для неавторизованных пользователей
  • передать auth-состояние в SSR через rootAuthLoader
  • исправить конфликт Router-контекстов в React Router v8

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

  • Настрой авторизацию Clerk для проекта на React Router v8 и покажи изменения в root.tsx и vite.config.ts.
  • Проверь loader дашборда: получи userId через getAuth(args), закрой маршрут для гостя и верни данные пользователя.
  • Добавь выбор организации через OrganizationSwitcher и загрузку данных организации по orgId.

Как установить clerk-react-router-patterns

1Через Skills CLI (Vercel)

npx skills add clerk/skills --skill clerk-react-router-patterns -a claude-code

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

~/.claude/skills/clerk-react-router-patterns/SKILL.md

Папка скилла целиком; для одного проекта — .claude/skills/clerk-react-router-patterns/

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

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

clerk-cli Скилл учит агента работать с бинарником clerk вместо ручных curl: пользователи, организации, сессии, вебхуки, деплой. CX Codex +1 33 800установок clerk Разбирает запрос про Clerk и отправляет к нужному скиллу: настройка, CLI, паттерны фреймворков, биллинг, вебхуки. CX Codex +1 30 000установок clerk-react-patterns Скилл помогает настроить аутентификацию в React SPA на базе @clerk/react. Пригодится при сборке проектов на Vite или Create React App с закрытыми маршрутами. CX Codex +1 19 700установок clerk-billing Скилл для работы с Clerk Billing: тарифы, чекаут, ограничение функций по плану и вебхуки подписок. CX Codex +1 16 900установок clerk-tanstack-patterns Подсказывает агенту, как подключить Clerk к TanStack React Start: защита маршрутов, createServerFn, лоадеры и middleware. CX Codex +1 15 500установок clerk-swift Собирает экраны входа Clerk в нативных приложениях iOS и macOS: готовые вью ClerkKitUI или свои сценарии на ClerkKit. CX Codex +1 14 500установок clerk-chrome-extension-patterns Набор инструкций по интеграции @clerk/chrome-extension в браузерные расширения. Помогает настроить вход в popup, сессии в service worker и делегирование OAuth через веб-приложение. CX Codex +1 14 400установок clerk-astro-patterns Подсказывает агенту, как подключить Clerk к Astro: middleware, защита SSR-страниц, авторизация в API-роутах и островных компонентах. CX Codex +1 14 300установок

Похожие

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установок

Рядом в теме «Фронтенд и UI»

Всё по теме «Фронтенд и UI» →

Вопросы о clerk-react-router-patterns

Как установить clerk-react-router-patterns в Claude Code?

Выполните npx skills add clerk/skills --skill clerk-react-router-patterns -a claude-code, затем откройте ~/.claude/skills/clerk-react-router-patterns/SKILL.md.

Что делает clerk-react-router-patterns?

Скилл объясняет настройку Clerk для React Router v7/v8: middleware, rootAuthLoader, getAuth в loaders и actions, защищённые маршруты, SSR и переключение организаций.

Чем отличается настройка React Router v7 от v8?

В v7 нужно включить future: { v8_middleware: true } в react-router.config.ts. В v8 этот флаг убирать, а в vite.config.ts добавить ssr: { noExternal: ['@clerk/react-router'] }.

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

SKILL.md · MIT
---
name: clerk-react-router-patterns
description: 'React Router v7/v8 patterns with Clerk — rootAuthLoader, getAuth in loaders,
  clerkMiddleware, protected routes, SSR user data, org switching. Triggers on: react-router
  auth, rootAuthLoader, getAuth loader, react-router protected route, loader authentication,
  SSR auth react-router, useNavigate may be used only in the context of a Router.'
license: MIT
allowed-tools: WebFetch
metadata:
  author: clerk
  version: 1.1.0
---

# React Router Patterns

SDK: `@clerk/react-router` v3.5+. Supports React Router v7.9+ and v8.

## What Do You Need?

| Task | Reference |
|------|-----------|
| Auth in loaders and actions | references/loaders-actions.md |
| Protected routes and redirects | references/protected-routes.md |
| SSR user data and session | references/ssr-auth.md |

## React Router v7 vs v8

Check the installed `react-router` major version before scaffolding — the config differs:

| | v7.9+ | v8+ |
|--|--|--|
| Middleware API | Opt-in: set `future: { v8_middleware: true }` in `react-router.config.ts` | Always on — do NOT set the flag (v8 removed it) |
| `ssr.noExternal` workaround (below) | Not needed | **Required** |

## Minimal Setup

### 1. vite.config.ts (v8 only — REQUIRED)

React Router v8 ships development/production conditional exports. In `react-router dev`,
Vite externalizes `@clerk/react-router` for SSR, so Node resolves the production build of
react-router while the app code gets the development build — two module instances, two
Router contexts. Every request then fails during SSR with:

```
Error: useNavigate() may be used only in the context of a <Router> component.
```

**`npm ls react-router` shows a single copy — that does NOT rule this out.** The
duplication is per export condition, not per installed copy. Do not chase duplicate
installs; add the workaround (upstream issue:
https://github.com/remix-run/react-router/issues/15232):

```ts
import { reactRouter } from '@react-router/dev/vite'
import { defineConfig } from 'vite'

export default defineConfig({
  plugins: [reactRouter()],
  ssr: {
    noExternal: ['@clerk/react-router'],
  },
})
```

### 2. root.tsx

```tsx
import { Outlet } from 'react-router'
import { rootAuthLoader, clerkMiddleware } from '@clerk/react-router/server'
import { ClerkProvider } from '@clerk/react-router'
import type { Route } from './+types/root'

export const middleware: Route.MiddlewareFunction[] = [clerkMiddleware()]

export async function loader(args: Route.LoaderArgs) {
  return rootAuthLoader(args)
}

export default function App({ loaderData }: Route.ComponentProps) {
  return (
    <ClerkProvider loaderData={loaderData}>
      <Outlet />
    </ClerkProvider>
  )
}
```

There is no `ClerkApp` HOC in `@clerk/react-router` (that was the `@clerk/remix` API).
Render `<ClerkProvider loaderData={loaderData}>` inside the default export and pass it
the root route's `loaderData`.

### 3. react-router.config.ts (v7 only)

```ts
import type { Config } from '@react-router/dev/config'

export default {
  future: {
    v8_middleware: true,
  },
} satisfies Config
```

On v8, omit the `future` block entirely — the flag no longer exists.

> **Required**: `rootAuthLoader` must be called in `root.tsx`'s loader. Without it, `getAuth` throws in nested loaders.

## Mental Model

React Router v7/v8 uses a middleware + loader pipeline. Clerk plugs into both layers:

- **Middleware** (`clerkMiddleware()`) — runs on every request, attaches auth to context
- **`rootAuthLoader`** — required in `root.tsx` to pass Clerk state to the client
- **`getAuth(args)`** — called inside any loader/action to get the current user

```
Request → clerkMiddleware() → rootAuthLoader → page loader → component
                 ↓                   ↓               ↓
           attaches auth      injects state     getAuth(args)
           to context         to response       reads context
```

## Auth in Loaders

```tsx
import { getAuth } from '@clerk/react-router/server'
import type { Route } from './+types/dashboard'

export async function loader(args: Route.LoaderArgs) {
  const { userId } = await getAuth(args)
  if (!userId) throw redirect('/sign-in')

  const data = await fetchUserData(userId)
  return { data }
}
```

## Auth in Actions

```tsx
import { getAuth } from '@clerk/react-router/server'

export async function action(args: Route.ActionArgs) {
  const { userId, orgId } = await getAuth(args)
  if (!userId) throw new Response('Unauthorized', { status: 401 })

  const formData = await args.request.formData()
  await saveData(userId, orgId, formData)
  return redirect('/dashboard')
}
```

## Client Components

```tsx
import { useAuth, useUser } from '@clerk/react-router'

export function Profile() {
  const { userId, isSignedIn } = useAuth()
  const { user } = useUser()
  if (!isSignedIn) return null
  return <p>{user?.firstName}</p>
}
```

## Org Switching

```tsx
import { OrganizationSwitcher } from '@clerk/react-router'

export function Nav() {
  return <OrganizationSwitcher afterSelectOrganizationUrl="/dashboard" />
}
```

```tsx
export async function loader(args: Route.LoaderArgs) {
  const { userId, orgId } = await getAuth(args)
  if (!userId) throw redirect('/sign-in')
  if (!orgId) throw redirect('/select-org')

  return { data: await fetchOrgData(orgId) }
}
```

## Common Pitfalls

| Symptom | Cause | Fix |
|---------|-------|-----|
| `useNavigate() may be used only in the context of a <Router>` thrown from ClerkProvider during SSR in dev (v8) | Vite dev SSR externalizes `@clerk/react-router`, which then loads react-router's production build while the app uses the development build — two Router contexts. A single copy in `npm ls` does not rule this out. | Add `ssr: { noExternal: ['@clerk/react-router'] }` to `vite.config.ts`. Do NOT downgrade to v7 |
| Build error: `ClerkApp` is not exported | `ClerkApp` does not exist in `@clerk/react-router` | Use `<ClerkProvider loaderData={loaderData}>` in root.tsx's default export |
| `clerkMiddleware() not detected` | Missing middleware (or on v7, missing `v8_middleware` future flag) | Export `middleware = [clerkMiddleware()]` from root route; on v7 also set `future: { v8_middleware: true }` |
| Unknown future flag error/warning (v8) | `v8_middleware` flag left in `react-router.config.ts` after upgrading | Remove the `future.v8_middleware` entry — middleware is always on in v8 |
| `getAuth` returns empty userId | `rootAuthLoader` not called | Call `rootAuthLoader(args)` in `root.tsx` loader |
| Infinite redirect loop | Redirect target is also protected | Exclude `/sign-in` from protection check |
| `redirect` not working in action | Using `Response` instead of `throw redirect()` | Use `throw redirect('/path')` from `react-router` |

## Import Map

| What | Import From |
|------|-------------|
| `getAuth` | `@clerk/react-router/server` |
| `rootAuthLoader` | `@clerk/react-router/server` |
| `clerkMiddleware` | `@clerk/react-router/server` |
| `ClerkProvider` | `@clerk/react-router` |
| `useAuth`, `useUser` | `@clerk/react-router` |
| `OrganizationSwitcher` | `@clerk/react-router` |

## See Also

- `clerk-setup` - Initial Clerk install
- `clerk-custom-ui` - Custom flows & appearance
- `clerk-orgs` - B2B organizations

## Docs

[React Router SDK](https://clerk.com/docs/react-router/getting-started/quickstart)

© clerk · MIT · clerk/skills

Смотрите также

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

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