Clerk Authentication

Drop-in authentication for modern web apps. Handles login UI, social providers, session management, organizations, and RBAC.

25 stars

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

$curl -o ~/.claude/skills/clerk-auth/SKILL.md --create-dirs "https://raw.githubusercontent.com/ComeOnOliver/skillshub/main/skills/TerminalSkills/skills/clerk-auth/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/clerk-auth/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How Clerk Authentication Compares

Feature / AgentClerk AuthenticationStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/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 flows

Related Skills

clerk-webhooks-events

25
from ComeOnOliver/skillshub

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

25
from ComeOnOliver/skillshub

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

25
from ComeOnOliver/skillshub

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

25
from ComeOnOliver/skillshub

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

25
from ComeOnOliver/skillshub

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

25
from ComeOnOliver/skillshub

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

25
from ComeOnOliver/skillshub

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

25
from ComeOnOliver/skillshub

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

25
from ComeOnOliver/skillshub

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

25
from ComeOnOliver/skillshub

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

25
from ComeOnOliver/skillshub

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

25
from ComeOnOliver/skillshub

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".