Clerk Authentication
Drop-in authentication for modern web apps. Handles login UI, social providers, session management, organizations, and RBAC.
Best use case
Clerk Authentication is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Drop-in authentication for modern web apps. Handles login UI, social providers, session management, organizations, and RBAC.
Teams using Clerk Authentication should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/clerk-auth/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How Clerk Authentication Compares
| Feature / Agent | Clerk Authentication | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Drop-in authentication for modern web apps. Handles login UI, social providers, session management, organizations, and RBAC.
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# Clerk Authentication
Drop-in authentication for modern web apps. Handles login UI, social providers, session management, organizations, and RBAC.
## Setup (Next.js)
```bash
npm install @clerk/nextjs
```
```env
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_live_...
CLERK_SECRET_KEY=sk_live_...
```
```typescript
// app/layout.tsx — Wrap app in ClerkProvider
import { ClerkProvider } from '@clerk/nextjs';
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<ClerkProvider>
<html><body>{children}</body></html>
</ClerkProvider>
);
}
```
## Middleware (Route Protection)
```typescript
// middleware.ts — Protect routes at the edge
import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server';
const isPublicRoute = createRouteMatcher([
'/',
'/pricing',
'/sign-in(.*)',
'/sign-up(.*)',
'/api/webhooks(.*)',
]);
export default clerkMiddleware(async (auth, req) => {
if (!isPublicRoute(req)) {
await auth.protect();
}
});
export const config = {
matcher: ['/((?!.*\\..*|_next).*)', '/', '/(api|trpc)(.*)'],
};
```
## Server-Side Auth
### Server Components (App Router)
```typescript
import { auth, currentUser } from '@clerk/nextjs/server';
export default async function Page() {
// Quick access to IDs and role
const { userId, orgId, orgRole } = await auth();
// Full user object when needed
const user = await currentUser();
return <p>Hello {user?.firstName}</p>;
}
```
### API Routes
```typescript
import { auth } from '@clerk/nextjs/server';
import { NextResponse } from 'next/server';
export async function GET() {
const { userId, orgId } = await auth();
if (!userId) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
// ... fetch data scoped to orgId
}
```
### Server Actions
```typescript
'use server';
import { auth } from '@clerk/nextjs/server';
export async function createProject(name: string) {
const { userId, orgId, orgRole } = await auth();
if (!orgId || (orgRole !== 'org:admin' && orgRole !== 'org:owner')) {
throw new Error('Forbidden');
}
return db.projects.create({ data: { name, orgId, createdBy: userId } });
}
```
## Client-Side Auth
```typescript
'use client';
import { useAuth, useUser, useOrganization } from '@clerk/nextjs';
export function ProfileCard() {
const { isSignedIn, userId } = useAuth();
const { user } = useUser();
const { organization, membership } = useOrganization();
if (!isSignedIn) return <p>Not signed in</p>;
return (
<div>
<p>{user?.fullName}</p>
<p>Org: {organization?.name}</p>
<p>Role: {membership?.role}</p>
</div>
);
}
```
## Pre-Built Components
```typescript
import {
SignIn, // Full sign-in page
SignUp, // Full sign-up page
UserButton, // Avatar dropdown (profile, sign out)
UserProfile, // Full profile management page
OrganizationSwitcher, // Org dropdown + create org
OrganizationList, // List orgs + join/create
OrganizationProfile, // Org settings (members, roles)
} from '@clerk/nextjs';
// Sign-in page
// app/sign-in/[[...sign-in]]/page.tsx
export default function SignInPage() {
return <SignIn />;
}
// Header with org switcher and user menu
export function Header() {
return (
<nav>
<OrganizationSwitcher hidePersonal={true} />
<UserButton afterSignOutUrl="/" />
</nav>
);
}
```
## Organizations (Multi-Tenant)
Enable at dashboard.clerk.com → Organizations.
### Create Organization
```typescript
import { auth, clerkClient } from '@clerk/nextjs/server';
async function createOrg(name: string) {
const { userId } = await auth();
const client = await clerkClient();
return client.organizations.createOrganization({
name,
createdBy: userId!,
});
}
```
### Invite Members
```typescript
async function inviteMember(orgId: string, email: string, role: string) {
const client = await clerkClient();
return client.organizations.createOrganizationInvitation({
organizationId: orgId,
emailAddress: email,
role, // 'org:admin', 'org:member', or custom roles
inviterUserId: (await auth()).userId!,
});
}
```
### Custom Roles
Define at dashboard.clerk.com → Organizations → Roles:
```
org:owner — Full access, can delete org
org:admin — Manage members, settings
org:member — Standard access
org:viewer — Read-only (custom)
org:billing — Billing management only (custom)
```
Check roles in code:
```typescript
const { orgRole, has } = await auth();
// Direct role check
if (orgRole === 'org:admin') { ... }
// Permission-based check (preferred — decouples code from role names)
if (has({ permission: 'org:projects:manage' })) { ... }
```
## Webhooks
Sync Clerk events to your database:
```typescript
// app/api/webhooks/clerk/route.ts
import { Webhook } from 'svix';
import { WebhookEvent } from '@clerk/nextjs/server';
export async function POST(req: Request) {
const wh = new Webhook(process.env.CLERK_WEBHOOK_SECRET!);
const body = await req.text();
const svixHeaders = {
'svix-id': req.headers.get('svix-id')!,
'svix-timestamp': req.headers.get('svix-timestamp')!,
'svix-signature': req.headers.get('svix-signature')!,
};
const event = wh.verify(body, svixHeaders) as WebhookEvent;
switch (event.type) {
case 'user.created':
await db.users.create({ data: {
clerkId: event.data.id,
email: event.data.email_addresses[0]?.email_address,
name: `${event.data.first_name} ${event.data.last_name}`.trim(),
}});
break;
case 'user.deleted':
await db.users.delete({ where: { clerkId: event.data.id } });
break;
case 'organization.created':
await db.orgs.create({ data: {
clerkOrgId: event.data.id,
name: event.data.name,
slug: event.data.slug,
}});
break;
}
return new Response('OK');
}
```
Key events: `user.created`, `user.updated`, `user.deleted`, `organization.created`, `organization.updated`, `organizationMembership.created`, `organizationMembership.deleted`.
## JWT Templates (API Auth)
For external APIs or microservices that need to verify Clerk tokens:
```typescript
// Configure at dashboard.clerk.com → JWT Templates
// Template name: "api-token"
// Claims: { "userId": "{{user.id}}", "orgId": "{{org.id}}", "role": "{{org.role}}" }
// Client: get a custom JWT
const { getToken } = useAuth();
const token = await getToken({ template: 'api-token' });
// External API: verify the JWT
import { createClerkClient } from '@clerk/backend';
const clerk = createClerkClient({ secretKey: process.env.CLERK_SECRET_KEY });
async function verifyRequest(req: Request) {
const token = req.headers.get('Authorization')?.replace('Bearer ', '');
if (!token) throw new Error('No token');
return clerk.verifyToken(token);
}
```
## Express.js
```typescript
import { ClerkExpressRequireAuth } from '@clerk/clerk-sdk-node';
// Protect routes
app.use('/api', ClerkExpressRequireAuth());
app.get('/api/me', (req, res) => {
res.json({ userId: req.auth.userId, orgId: req.auth.orgId });
});
```
## Guidelines
- **Middleware is the primary protection layer** — don't rely on component-level checks alone. Middleware runs at the edge before any page code.
- **Use `auth()` in server components, not `useAuth()`** — server-side checks can't be bypassed by the client
- **Webhook signature verification is mandatory** — use `svix` library to verify every webhook payload
- **Sync to your database via webhooks** — don't query Clerk's API for every database operation. Keep a local copy of users and orgs.
- **Use organizations for B2B** — even if you think you only need simple auth now. Adding multi-tenancy later is much harder than starting with it.
- **Permission-based checks over role checks** — `has({ permission: 'X' })` is more maintainable than `role === 'org:admin'`
- **`hidePersonal={true}` for B2B apps** — personal workspaces confuse users in team-based products
- **Configure sign-in/up URLs in env vars** — Clerk uses these for redirects after auth flowsRelated Skills
clerk-webhooks-events
Configure Clerk webhooks and handle authentication events. Use when setting up user sync, handling auth events, or integrating Clerk with external systems via Svix webhooks. Trigger with phrases like "clerk webhooks", "clerk events", "clerk user sync", "clerk svix", "clerk event handling".
clerk-upgrade-migration
Manage Clerk SDK version upgrades and handle breaking changes. Use when upgrading Clerk packages, migrating to new SDK versions, or handling deprecation warnings. Trigger with phrases like "upgrade clerk", "clerk migration", "update clerk SDK", "clerk breaking changes".
clerk-security-basics
Implement security best practices with Clerk authentication. Use when securing your application, reviewing auth implementation, or hardening Clerk configuration. Trigger with phrases like "clerk security", "secure clerk", "clerk best practices", "clerk hardening".
clerk-sdk-patterns
Common Clerk SDK patterns and best practices. Use when implementing authentication flows, accessing user data, or integrating Clerk SDK methods in your application. Trigger with phrases like "clerk SDK", "clerk patterns", "clerk best practices", "clerk API usage".
clerk-reference-architecture
Reference architecture patterns for Clerk authentication. Use when designing application architecture, planning auth flows, or implementing enterprise-grade authentication. Trigger with phrases like "clerk architecture", "clerk design", "clerk system design", "clerk integration patterns".
clerk-rate-limits
Understand and manage Clerk rate limits and quotas. Use when hitting rate limits, optimizing API usage, or planning for high-traffic scenarios. Trigger with phrases like "clerk rate limit", "clerk quota", "clerk API limits", "clerk throttling".
clerk-prod-checklist
Production readiness checklist for Clerk deployment. Use when preparing to deploy, reviewing production configuration, or auditing Clerk implementation before launch. Trigger with phrases like "clerk production", "clerk deploy checklist", "clerk go-live", "clerk launch ready".
clerk-performance-tuning
Optimize Clerk authentication performance. Use when improving auth response times, reducing latency, or optimizing Clerk SDK usage. Trigger with phrases like "clerk performance", "clerk optimization", "clerk slow", "clerk latency", "optimize clerk".
clerk-observability
Implement monitoring, logging, and observability for Clerk authentication. Use when setting up monitoring, debugging auth issues in production, or implementing audit logging. Trigger with phrases like "clerk monitoring", "clerk logging", "clerk observability", "clerk metrics", "clerk audit log".
clerk-multi-env-setup
Configure Clerk for multiple environments (dev, staging, production). Use when setting up environment-specific configurations, managing multiple Clerk instances, or implementing environment promotion. Trigger with phrases like "clerk environments", "clerk staging", "clerk dev prod", "clerk multi-environment".
clerk-migration-deep-dive
Migrate from other authentication providers to Clerk. Use when migrating from Auth0, Firebase, Supabase Auth, NextAuth, or custom authentication solutions. Trigger with phrases like "migrate to clerk", "clerk migration", "switch to clerk", "auth0 to clerk", "firebase auth to clerk".
clerk-local-dev-loop
Set up local development workflow with Clerk. Use when configuring development environment, testing auth locally, or setting up hot reload with Clerk. Trigger with phrases like "clerk local dev", "clerk development", "test clerk locally", "clerk dev environment".