
clerk-nextjs-skills
Clerk authentication for Next.js 16 (App Router only) with proxy.ts setup, migration from middleware.ts, environment configuration, and MCP server integration.
- Installs
- 436
- Last 24h
- —
- Trending rank
- —
- Security
- Not audited
Install
Works with every agent the skills CLI supports.
npx skills add https://github.com/gocallum/nextjs16-agent-skills --skill clerk-nextjs-skills- 01
Install
Run the command in your project. The CLI asks which agents to install for.
- 02
Describe the task
Ask your agent for something this skill covers. It loads clerk-nextjs-skills automatically when relevant.
- 03
Review the result
The agent follows the SKILL.md steps, scripts and references bundled with the skill.
SKILL.md
The instructions your agent reads when the skill is triggered.
Links
- Clerk Next.js Quickstart
- Clerk MCP Server Guide
- Clerk Next.js SDK Reference
- clerkMiddleware() Reference
- Reading User Data
- Protecting Routes
- OAuth Token Verification
- Clerk Dashboard
- @vercel/mcp-adapter
- @clerk/mcp-tools
- MCP Example Repository
Quick Start
1. Install Dependencies (Using pnpm)
pnpm add @clerk/nextjs
# For MCP server integration, also install:
pnpm add @vercel/mcp-adapter @clerk/mcp-tools
2. Create proxy.ts (Next.js 16)
The proxy.ts file replaces middleware.ts from Next.js 15. Create it at the root or in /src:
// proxy.ts (or src/proxy.ts)
import { clerkMiddleware } from '@clerk/nextjs/server'
export default clerkMiddleware()
export const config = {
matcher: [
'/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)',
'/(api|trpc)(.*)',
],
}
3. Set Environment Variables
Create .env.local in your project root:
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=your_publishable_key_here
CLERK_SECRET_KEY=your_secret_key_here
NEXT_PUBLIC_CLERK_SIGN_IN_URL=/sign-in
NEXT_PUBLIC_CLERK_SIGN_UP_URL=/sign-up
NEXT_PUBLIC_CLERK_AFTER_SIGN_IN_URL=/
NEXT_PUBLIC_CLERK_AFTER_SIGN_UP_URL=/
4. Add ClerkProvider to Layout
// app/layout.tsx
import {
ClerkProvider,
SignInButton,
SignUpButton,
SignedIn,
SignedOut,
UserButton,
} from '@clerk/nextjs'
import type { Metadata } from 'next'
export const metadata: Metadata = {
title: 'My App',
}
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<ClerkProvider>
<html lang="en">
<body>
<header className="flex justify-end items-center p-4 gap-4 h-16">
<SignedOut>
<SignInButton />
<SignUpButton />
</SignedOut>
<SignedIn>
<UserButton />
</SignedIn>
</header>
{children}
</body>
</html>
</ClerkProvider>
)
}
5. Run Your App
pnpm dev
Visit http://localhost:3000 and click "Sign Up" to create your first user.
Key Concepts
proxy.ts vs middleware.ts
- Next.js 16 (App Router): Use
proxy.tsfor Clerk middleware - Next.js ≤15: Use
middleware.tswith identical code (filename only differs) - Clerk's
clerkMiddleware()function is the same regardless of filename - The
matcherconfiguration ensures proper route handling and performance
Protecting Routes
By default, clerkMiddleware() does not protect routes—all are public. Use auth.protect() to require authentication:
// Protect specific route
import { auth } from '@clerk/nextjs/server'
export default async function Page() {
const { userId } = await auth()
if (!userId) {
// Redirect handled by clerkMiddleware
}
return <div>Protected content for {userId}</div>
}
Or protect all routes in proxy.ts:
import { clerkMiddleware } from '@clerk/nextjs/server'
export default clerkMiddleware(async (auth, req) => {
await auth.protect()
})
Environment Variable Validation
Check for required Clerk keys before runtime:
// lib/clerk-config.ts
export function validateClerkEnv() {
const required = [
'NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY',
'CLERK_SECRET_KEY',
]
const missing = required.filter(key => !process.env[key])
if (missing.length > 0) {
throw new Error(`Missing required Clerk environment variables: ${missing.join(', ')}`)
}
}
Accessing User Data
Use Clerk hooks in client components:
// app/components/user-profile.tsx
'use client'
import { useUser } from '@clerk/nextjs'
export function UserProfile() {
const { user, isLoaded } = useUser()
if (!isLoaded) return <div>Loading...</div>
if (!user) return <div>Not signed in</div>
return (
<div>
<h1>{user.fullName}</h1>
<p>{user.primaryEmailAddress?.emailAddress}</p>
</div>
)
}
Or in server components/actions:
// app/actions.ts
'use server'
import { auth, clerkClient } from '@clerk/nextjs/server'
export async function getUserData() {
const { userId } = await auth()
if (!userId) {
throw new Error('Unauthorized')
}
const clerk = await clerkClient()
const user = await clerk.users.getUser(userId)
return user
}
Migrating from middleware.ts (Next.js 15) to proxy.ts (Next.js 16)
Step-by-Step Migration
-
Rename the file from
middleware.tstoproxy.ts(location remains same: root or/src) -
Keep the code identical - No functional changes needed:
// Before (middleware.ts) import { clerkMiddleware } from '@clerk/nextjs/server' export default clerkMiddleware() export const config = { ... } // After (proxy.ts) - Same code import { clerkMiddleware } from '@clerk/nextjs/server' export default clerkMiddleware() export const config = { ... } -
Update Next.js version:
pnpm add next@latest -
Verify environment variables are still in
.env.local(no changes needed) -
Test the migration:
pnpm dev
Troubleshooting Migration
- If routes aren't protected, ensure
proxy.tsis in the correct location (root or/src) - Check that
.env.localhas all required Clerk keys - Clear
.nextcache if middleware changes don't take effect:rm -rf .next && pnpm dev - Verify Next.js version is 16.0+:
pnpm list next
Building an MCP Server with Clerk
See CLERK_MCP_SERVER_SETUP.md for complete MCP server integration.
Quick MCP Setup Summary
-
Install MCP dependencies:
pnpm add @vercel/mcp-adapter @clerk/mcp-tools -
Create MCP route at
app/[transport]/route.ts:import { verifyClerkToken } from '@clerk/mcp-tools/next' import { createMcpHandler, withMcpAuth } from '@vercel/mcp-adapter' import { auth, clerkClient } from '@clerk/nextjs/server' const clerk = await clerkClient() const handler = createMcpHandler((server) => { server.tool( 'get-clerk-user-data', 'Gets data about the Clerk user that authorized this request', {}, async (_, { authInfo }) => { const userId = authInfo!.extra!.userId! as string const userData = await clerk.users.getUser(userId) return { content: [{ type: 'text', text: JSON.stringify(userData) }], } }, ) }) const authHandler = withMcpAuth( handler, async (_, token) => { const clerkAuth = await auth({ acceptsToken: 'oauth_token' }) return verifyClerkToken(clerkAuth, token) }, { required: true, resourceMetadataPath: '/.well-known/oauth-protected-resource/mcp', }, ) export { authHandler as GET, authHandler as POST } -
Expose OAuth metadata endpoints (see references for complete setup)
-
Update proxy.ts to exclude
.well-knownendpoints:import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server' const isPublicRoute = createRouteMatcher([ '/.well-known/oauth-authorization-server(.*)', '/.well-known/oauth-protected-resource(.*)', ]) export default clerkMiddleware(async (auth, req) => { if (isPublicRoute(req)) return await auth.protect() }) -
Enable Dynamic Client Registration in Clerk Dashboard
Best Practices
1. Environment Variable Management
- Always use
.env.localfor development (never commit sensitive keys) - Validate environment variables on application startup
- Use
NEXT_PUBLIC_prefix ONLY for non-sensitive keys that are safe to expose - For production, set environment variables in your deployment platform (Vercel, etc.)
2. Route Protection Strategies
// Option A: Protect all routes
export default clerkMiddleware(async (auth, req) => {
await auth.protect()
})
// Option B: Protect specific routes
import { createRouteMatcher } from '@clerk/nextjs/server'
const isProtectedRoute = createRouteMatcher(['/dashboard(.*)', '/api/user(.*)'])
export default clerkMiddleware(async (auth, req) => {
if (isProtectedRoute(req)) {
await auth.protect()
}
})
// Option C: Public routes with opt-in protection
const isPublicRoute = createRouteMatcher(['/sign-in(.*)', '/sign-up(.*)'])
export default clerkMiddleware(async (auth, req) => {
if (!isPublicRoute(req)) {
await auth.protect()
}
})
3. MCP Server Security
- Enable Dynamic Client Registration in Clerk Dashboard
- Keep
.well-knownendpoints public but protect all MCP tools with OAuth - Use
acceptsToken: 'oauth_token'inauth()to require machine tokens - OAuth tokens are free during public beta (pricing TBD)
- Always verify tokens with
verifyClerkToken()before exposing user data
4. Performance & Caching
- Use
clerkClient()for server-side user queries (cached automatically) - Leverage React Server Components for secure user data access
- Cache user data when possible to reduce API calls
- Use
@clerk/nextjshooks only in Client Components ('use client')
5. Production Deployment
- Set all environment variables in your deployment platform
- Use Clerk's production instance keys (not development keys)
- Test authentication flow in staging environment before production
- Monitor Clerk Dashboard for authentication errors
- Keep
@clerk/nextjsupdated:pnpm update @clerk/nextjs
Troubleshooting
Issues & Solutions
| Issue | Solution |
|---|---|
| "Missing environment variables" | Ensure .env.local has NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY and CLERK_SECRET_KEY |
| Middleware not protecting routes | Verify proxy.ts is in root or /src directory, not in app/ |
| Sign-in/sign-up pages not working | Check NEXT_PUBLIC_CLERK_SIGN_IN_URL and NEXT_PUBLIC_CLERK_SIGN_UP_URL in .env.local |
| User data returns null | Ensure user is authenticated: check userId is not null before calling getUser() |
| MCP server OAuth fails | Enable Dynamic Client Registration in Clerk Dashboard OAuth Applications |
| Changes not taking effect | Clear .next cache: rm -rf .next and restart pnpm dev |
| "proxy.ts" not recognized | Verify Next.js version is 16.0+: pnpm list next |
Common Next.js 16 Gotchas
- File naming: Must be
proxy.ts(notmiddleware.ts) for Next.js 16 - Location: Place
proxy.tsat project root or in/srcdirectory, NOT inapp/ - Re-exports: Config object must be exported from
proxy.tsfor matcher to work - Async operations:
clerkMiddleware()is async-ready; useawait auth.protect()for route protection
Debug Mode
Enable debug logging:
// proxy.ts
import { clerkMiddleware } from '@clerk/nextjs/server'
export default clerkMiddleware((auth, req) => {
if (process.env.DEBUG_CLERK) {
console.log('Request URL:', req.nextUrl.pathname)
console.log('User ID:', auth.sessionClaims?.sub)
}
})
Run with debug:
DEBUG_CLERK=1 pnpm dev
Related Skills
- mcp-server-skills: General MCP server patterns with Vercel adapter
- nextjs16-skills: Next.js 16 features, breaking changes, and best practices
- authjs-skills: Alternative authentication using Auth.js (Auth0, GitHub, etc.)
Resources
FAQ
What does the clerk-nextjs-skills skill do?
Clerk authentication for Next.js 16 (App Router only) with proxy.ts setup, migration from middleware.ts, environment configuration, and MCP server integration.
How do I install clerk-nextjs-skills?
Run npx skills add https://github.com/gocallum/nextjs16-agent-skills --skill clerk-nextjs-skills in your project. The skills CLI detects the agents you use and copies the skill into the right folder. For Claude Code you can also place the skill folder at ~/.claude/skills/clerk-nextjs-skills/ (personal) or .claude/skills/clerk-nextjs-skills/ (project).
Which AI agents can use clerk-nextjs-skills?
Any agent that supports the open Agent Skills format (a folder with a SKILL.md file), including Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Cline, OpenCode and more.
Is clerk-nextjs-skills safe to install?
No partner security audit is available yet. Skills can run commands and scripts, so read the SKILL.md and any bundled files before installing.
Who maintains clerk-nextjs-skills?
It is published by gocallum in gocallum/nextjs16-agent-skills. It has 436 recorded installs.
More from gocallum/nextjs16-agent-skills
prisma-orm-v7-skills
gocallum/nextjs16-agent-skills
Key facts and breaking changes for upgrading to Prisma ORM 7. Consider version 7 changes before generation or troubleshooting
authjs-skills
gocallum/nextjs16-agent-skills
Auth.js v5 setup for Next.js authentication including Google OAuth, credentials provider, environment configuration, and core API integration
nextjs16-skills
gocallum/nextjs16-agent-skills
Key facts and links for Next.js 16. Use for planning, writing, and troubleshooting Next.js 16 changes.
ai-sdk-6-skills
gocallum/nextjs16-agent-skills
AI SDK 6 Beta overview, agents, tool approval, Groq (Llama), and Vercel AI Gateway. Key breaking changes from v5 and new patterns.
resend-integration-skills
gocallum/nextjs16-agent-skills
Integrate Resend email service via MCP protocol for AI agents to send emails with Claude Desktop, GitHub Copilot, and Cursor. Set up transactional and marketing emails, configure sender verification, and use AI to automate email workflows.
mcp-server-skills
gocallum/nextjs16-agent-skills
Pattern for building MCP servers in Next.js with mcp-handler, shared Zod schemas, and reusable server actions.
Popular frontend & design skills
setup-matt-pocock-skills
mattpocock/skills
Configure this repo for the engineering skills: set up its issue tracker, triage label vocabulary, and domain doc layout. Run once before first use of the other engineering skills.
frontend-design
anthropics/skills
Guidance for distinctive, intentional visual design when building new UI or reshaping an existing one. Helps with aesthetic direction, typography, and making choices that don't read as templated defaults.
hyperframes-animation
heygen-com/hyperframes
All animation knowledge for HyperFrames — atomic motion rules, multi-phase scene blueprints, scene transitions, broader motion-design techniques, AND the seven runtime adapters (GSAP default, plus Lottie, Three.js, Anime.js, CSS keyframes, Web Animations API, TypeGPU). Use for any motion or animation task: pick 2-4 rules and compose, or load a blueprint, or look up runtime-specific API (e.g. GSAP eases / Lottie player / Three.js mixer). Also covers auditing an existing composition's choreography (animation map) and 24 named text-animation effects. HyperFrames-native: single paused timeline, seek-safe, deterministic.
prototype
mattpocock/skills
Build a throwaway prototype to answer a design question. Use when the user wants to sanity-check whether a state model or logic feels right, or explore what a UI should look like.
hyperframes-core
heygen-com/hyperframes
The HyperFrames composition contract — build one renderable project. Use for composition structure, the data- timing attributes, class="clip", tracks, sub-compositions, variables, framework-owned media playback, deterministic-render rules, and validation. Read before writing composition HTML.
vercel-react-best-practices
vercel-labs/agent-skills
React and Next.js performance optimization guidelines from Vercel Engineering. This skill should be used when writing, reviewing, or refactoring React/Next.js code to ensure optimal performance patterns. Triggers on tasks involving React components, Next.js pages, data fetching, bundle optimization, or performance improvements.