From clerk-pack
Generates authenticated Clerk requests in Next.js: server auth()/currentUser(), protected API routes, client hooks. Verifies integration after Clerk setup.
How this skill is triggered — by the user, by Claude, or both
Slash command
/clerk-pack:clerk-hello-worldThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Make your first authenticated requests using Clerk across server components, client components, API routes, and server actions. Validates your Clerk integration end-to-end.
Make your first authenticated requests using Clerk across server components, client components, API routes, and server actions. Validates your Clerk integration end-to-end.
clerk-install-auth completed)NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY, CLERK_SECRET_KEY)// app/dashboard/page.tsx
import { auth, currentUser } from '@clerk/nextjs/server'
import { redirect } from 'next/navigation'
export default async function DashboardPage() {
// auth() is lightweight — reads JWT from the session cookie, no API call
const { userId } = await auth()
if (!userId) redirect('/sign-in')
// currentUser() makes a Backend API call — use sparingly, counts toward rate limit
const user = await currentUser()
return (
<div>
<h1>Hello, {user?.firstName || 'User'}!</h1>
<p>User ID: {userId}</p>
<p>Email: {user?.emailAddresses[0]?.emailAddress}</p>
<p>Created: {user?.createdAt ? new Date(user.createdAt).toLocaleDateString() : 'N/A'}</p>
</div>
)
}
Key distinction: auth() is cheap (JWT parsing, no network). currentUser() is expensive (Backend API call, rate-limited). Prefer auth() when you only need userId, orgId, or sessionClaims.
// app/api/hello/route.ts
import { auth } from '@clerk/nextjs/server'
export async function GET() {
const { userId, orgId, sessionClaims } = await auth()
if (!userId) {
return Response.json({ error: 'Unauthorized' }, { status: 401 })
}
return Response.json({
message: 'Hello from Clerk!',
userId,
orgId: orgId || null,
sessionId: sessionClaims?.sid,
timestamp: new Date().toISOString(),
})
}
'use client'
import { useUser, useAuth, useClerk } from '@clerk/nextjs'
export function AuthTest() {
const { user, isLoaded, isSignedIn } = useUser()
const { getToken, signOut } = useAuth()
const { openUserProfile } = useClerk()
if (!isLoaded) return <div>Loading...</div>
if (!isSignedIn) return <div>Not signed in</div>
const testAPI = async () => {
// getToken() returns the session JWT — use for calling your own API routes
// or external services with Bearer token auth
const token = await getToken()
const res = await fetch('/api/hello', {
headers: { Authorization: `Bearer ${token}` },
})
const data = await res.json()
console.log('API response:', data)
}
return (
<div>
<p>Signed in as: {user.primaryEmailAddress?.emailAddress}</p>
<img src={user.imageUrl} alt="Avatar" width={48} height={48} />
<div className="flex gap-2 mt-4">
<button onClick={testAPI}>Test API</button>
<button onClick={() => openUserProfile()}>Profile</button>
<button onClick={() => signOut()}>Sign Out</button>
</div>
</div>
)
}
// app/actions.ts
'use server'
import { auth } from '@clerk/nextjs/server'
export async function greetUser() {
const { userId } = await auth()
if (!userId) throw new Error('Unauthorized')
// Perform server-side work here (DB queries, external API calls, etc.)
return { greeting: `Hello user ${userId}!`, timestamp: new Date().toISOString() }
}
// app/dashboard/greeting.tsx
'use client'
import { greetUser } from '@/app/actions'
import { useState } from 'react'
export function GreetingButton() {
const [msg, setMsg] = useState<string | null>(null)
return (
<div>
<button onClick={async () => {
const result = await greetUser()
setMsg(result.greeting)
}}>
Get Server Greeting
</button>
{msg && <p>{msg}</p>}
</div>
)
}
import express from 'express'
import { clerkMiddleware, requireAuth, getAuth } from '@clerk/express'
const app = express()
app.use(clerkMiddleware())
// Public endpoint
app.get('/api/hello', (req, res) => {
const { userId } = getAuth(req)
res.json({
message: userId ? `Hello user ${userId}!` : 'Hello anonymous!',
authenticated: !!userId,
})
})
// Protected endpoint — returns 403 if no valid session
app.get('/api/me', requireAuth(), (req, res) => {
const { userId, orgId } = getAuth(req)
res.json({ userId, orgId })
})
app.listen(3001)
| Error | Cause | Solution |
|---|---|---|
userId is null | User not authenticated | Redirect to /sign-in or check middleware covers route |
currentUser() returns null | Session expired or invalid | Refresh page; ensure middleware is running |
| 401 from API route | Token missing or expired | Include Authorization: Bearer <token> header |
| Hydration mismatch | Server/client state differs | Guard client components with isLoaded check |
auth() was called but Clerk can't detect clerkMiddleware() | Middleware not in project root | Move middleware.ts out of app/ to project root |
auth() over currentUser() in hot paths to avoid Backend API rate limitscurrentUser() calls with React's cache() function across server components in the same request@clerk/backend or @clerk/expressProceed to clerk-local-dev-loop for local development workflow setup.
npx claudepluginhub jeremylongshore/claude-code-plugins-plus-skills --plugin clerk-packInstalls Clerk SDK and configures authentication for Next.js, React, or Express apps. Sets up env vars, ClerkProvider, middleware, and verifies initial auth.
Provides expert patterns for Clerk auth in Next.js App Router: providers, middleware, route protection, sign-in/up pages, organizations, webhooks, user sync. Use for secure auth setup.
Complete Next.js integration patterns for Clerk authentication with App Router and Pages Router. Use when setting up Clerk in Next.js, configuring authentication middleware, implementing protected routes, setting up server/client components with auth, or when user mentions Clerk Next.js setup, App Router auth, Pages Router auth, or Next.js authentication integration.