Try Live
Add Docs
Rankings
Pricing
Enterprise
Docs
Install
Theme
Install
Docs
Pricing
Enterprise
More...
More...
Try Live
Rankings
Create API Key
Add Docs
Clerk JavaScript
https://github.com/clerk/javascript
Admin
The official Clerk JavaScript SDKs provide developers with tools to build user management, including
...
Tokens:
64,668
Snippets:
430
Trust Score:
8.4
Update:
3 days ago
Context
Skills
Chat
Benchmark
76.3
Suggestions
Latest
Show doc for...
Code
Info
Show Results
Context Summary (auto-generated)
Raw
Copy
Link
# Clerk JavaScript SDKs Clerk is a complete authentication and user management platform for JavaScript applications. This monorepo contains the official Clerk JavaScript SDKs under the `@clerk` namespace, providing drop-in authentication UI components, session management, multi-tenancy with organizations, and a comprehensive backend API for managing users, sessions, and organizations programmatically. The SDK ecosystem supports multiple frameworks including Next.js, React, Express, Fastify, Hono, Astro, Vue, Nuxt, Expo, and more. It provides both client-side React components and hooks for building authentication flows, as well as server-side utilities for protecting routes, verifying sessions, and interacting with Clerk's Backend API. The architecture separates concerns into framework-specific packages that build upon shared core packages (`@clerk/backend`, `@clerk/shared`, `@clerk/clerk-js`). --- ## ClerkProvider Component The `ClerkProvider` component wraps your application and provides Clerk context to all child components. It must be placed at the root of your application to enable authentication features. ```tsx // app/layout.tsx (Next.js App Router) import { ClerkProvider } from '@clerk/nextjs'; export default function RootLayout({ children }: { children: React.ReactNode }) { return ( <ClerkProvider publishableKey={process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY} signInUrl="/sign-in" signUpUrl="/sign-up" afterSignInUrl="/dashboard" afterSignUpUrl="/onboarding" > <html lang="en"> <body>{children}</body> </html> </ClerkProvider> ); } ``` --- ## clerkMiddleware (Next.js) The `clerkMiddleware()` function integrates Clerk authentication into Next.js applications through middleware. It handles session verification, protects routes, and provides authentication state to server components. ```typescript // middleware.ts import { clerkMiddleware } from '@clerk/nextjs/server'; // Basic usage - authenticates all requests export default clerkMiddleware(); // With route protection export default clerkMiddleware((auth, request) => { const { userId, sessionId } = auth(); // Protect specific routes if (request.nextUrl.pathname.startsWith('/dashboard')) { if (!userId) { return auth().redirectToSignIn(); } } // Protect with role-based access if (request.nextUrl.pathname.startsWith('/admin')) { auth().protect({ role: 'org:admin' }); } }); export const config = { matcher: ['/((?!.*\\..*|_next).*)', '/', '/(api|trpc)(.*)'], }; ``` --- ## auth() Function (Next.js Server) The `auth()` function retrieves the authentication state in Next.js server components, route handlers, and server actions. It provides access to the current user's session and includes helper methods for protecting resources. ```typescript // app/dashboard/page.tsx (Server Component) import { auth } from '@clerk/nextjs/server'; export default async function DashboardPage() { const { userId, sessionClaims, orgId, orgRole } = await auth(); if (!userId) { return <div>Please sign in to access the dashboard</div>; } return ( <div> <h1>Welcome, User {userId}</h1> <p>Organization: {orgId || 'Personal account'}</p> <p>Role: {orgRole || 'N/A'}</p> </div> ); } // app/api/protected/route.ts (Route Handler) import { auth } from '@clerk/nextjs/server'; import { NextResponse } from 'next/server'; export async function GET() { const { userId } = await auth(); if (!userId) { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); } return NextResponse.json({ message: 'Protected data', userId }); } // Using auth.protect() for automatic protection export async function POST() { const { userId } = await auth.protect(); // Throws 401 if not authenticated // User is guaranteed to be authenticated here return NextResponse.json({ userId }); } ``` --- ## useAuth Hook The `useAuth()` hook provides access to the current user's authentication state and session management methods on the client side. It returns loading states, user identifiers, and utility functions for token retrieval. ```tsx 'use client'; import { useAuth } from '@clerk/nextjs'; export default function AuthStatus() { const { isLoaded, isSignedIn, userId, sessionId, orgId, orgRole, getToken, signOut, has } = useAuth(); if (!isLoaded) { return <div>Loading...</div>; } if (!isSignedIn) { return <div>Sign in to continue</div>; } const fetchProtectedData = async () => { const token = await getToken(); const response = await fetch('/api/protected', { headers: { Authorization: `Bearer ${token}` } }); return response.json(); }; // Check permissions const canManageUsers = has({ permission: 'org:users:manage' }); const isAdmin = has({ role: 'org:admin' }); return ( <div> <p>User ID: {userId}</p> <p>Session ID: {sessionId}</p> <p>Organization: {orgId || 'None'}</p> <p>Can manage users: {canManageUsers ? 'Yes' : 'No'}</p> <button onClick={fetchProtectedData}>Fetch Data</button> <button onClick={() => signOut()}>Sign Out</button> </div> ); } ``` --- ## useUser Hook The `useUser()` hook provides access to the current user's profile data including email addresses, phone numbers, profile image, and metadata. ```tsx 'use client'; import { useUser } from '@clerk/nextjs'; export default function UserProfile() { const { isLoaded, isSignedIn, user } = useUser(); if (!isLoaded) return <div>Loading...</div>; if (!isSignedIn) return <div>Not signed in</div>; return ( <div> <img src={user.imageUrl} alt="Profile" /> <h2>{user.fullName || user.username}</h2> <p>Email: {user.primaryEmailAddress?.emailAddress}</p> <p>Phone: {user.primaryPhoneNumber?.phoneNumber}</p> <p>Created: {user.createdAt?.toLocaleDateString()}</p> {/* Access user metadata */} <p>Role: {user.publicMetadata.role as string}</p> {/* Update user profile */} <button onClick={() => user.update({ firstName: 'New Name' })}> Update Name </button> </div> ); } ``` --- ## useOrganization Hook The `useOrganization()` hook provides access to the currently active organization's data, membership information, and management methods for multi-tenant applications. ```tsx 'use client'; import { useOrganization } from '@clerk/nextjs'; export default function OrganizationDashboard() { const { isLoaded, organization, membership, memberships, invitations, } = useOrganization({ memberships: { pageSize: 10 }, invitations: { pageSize: 5 }, }); if (!isLoaded) return <div>Loading...</div>; if (!organization) return <div>No organization selected</div>; return ( <div> <img src={organization.imageUrl} alt="Org logo" /> <h1>{organization.name}</h1> <p>Slug: {organization.slug}</p> <p>Your role: {membership?.role}</p> <p>Members: {organization.membersCount}</p> <h3>Members</h3> <ul> {memberships?.data?.map((member) => ( <li key={member.id}> {member.publicUserData.identifier} - {member.role} </li> ))} </ul> <h3>Pending Invitations</h3> <ul> {invitations?.data?.map((invite) => ( <li key={invite.id}> {invite.emailAddress} - {invite.status} <button onClick={() => invite.revoke()}>Revoke</button> </li> ))} </ul> {/* Invite new member */} <button onClick={() => organization.inviteMember({ emailAddress: 'new@example.com', role: 'org:member' })}> Invite Member </button> </div> ); } ``` --- ## SignIn and SignUp Components Pre-built authentication components that provide complete sign-in and sign-up flows with customizable appearance and routing options. ```tsx // app/sign-in/[[...sign-in]]/page.tsx import { SignIn } from '@clerk/nextjs'; export default function SignInPage() { return ( <SignIn path="/sign-in" routing="path" signUpUrl="/sign-up" forceRedirectUrl="/dashboard" appearance={{ elements: { rootBox: 'mx-auto', card: 'shadow-lg', headerTitle: 'text-2xl font-bold', socialButtonsBlockButton: 'bg-white border', }, variables: { colorPrimary: '#6366f1', borderRadius: '0.5rem', }, }} /> ); } // app/sign-up/[[...sign-up]]/page.tsx import { SignUp } from '@clerk/nextjs'; export default function SignUpPage() { return ( <SignUp path="/sign-up" routing="path" signInUrl="/sign-in" forceRedirectUrl="/onboarding" unsafeMetadata={{ referralSource: 'website' }} /> ); } ``` --- ## UserButton Component A pre-built component that renders the current user's avatar and provides a dropdown menu for profile management, organization switching, and sign out. ```tsx 'use client'; import { UserButton } from '@clerk/nextjs'; export default function Header() { return ( <header className="flex justify-between items-center p-4"> <h1>My App</h1> <UserButton afterSignOutUrl="/" appearance={{ elements: { avatarBox: 'w-10 h-10', userButtonPopoverCard: 'shadow-xl', }, }} userProfileMode="navigation" userProfileUrl="/user-profile" > {/* Custom menu items */} <UserButton.MenuItems> <UserButton.Link label="Settings" labelIcon={<SettingsIcon />} href="/settings" /> <UserButton.Action label="Help" labelIcon={<HelpIcon />} onClick={() => openHelp()} /> </UserButton.MenuItems> </UserButton> </header> ); } ``` --- ## OrganizationSwitcher Component A pre-built component that allows users to switch between organizations and create new ones in multi-tenant applications. ```tsx 'use client'; import { OrganizationSwitcher } from '@clerk/nextjs'; export default function Sidebar() { return ( <aside> <OrganizationSwitcher hidePersonal={false} afterCreateOrganizationUrl="/org/:slug" afterSelectOrganizationUrl="/org/:slug" afterSelectPersonalUrl="/dashboard" createOrganizationMode="modal" organizationProfileMode="navigation" organizationProfileUrl="/org-profile" appearance={{ elements: { rootBox: 'w-full', organizationSwitcherTrigger: 'p-2 w-full justify-start', }, }} /> </aside> ); } ``` --- ## createClerkClient (Backend API) The `createClerkClient()` function creates a backend API client for server-side operations like user management, organization management, and session verification. ```typescript // lib/clerk.ts import { createClerkClient } from '@clerk/backend'; const clerkClient = createClerkClient({ secretKey: process.env.CLERK_SECRET_KEY, publishableKey: process.env.CLERK_PUBLISHABLE_KEY, }); // Get a user by ID const user = await clerkClient.users.getUser('user_123'); // List all users with pagination const { data: users, totalCount } = await clerkClient.users.getUserList({ limit: 10, offset: 0, orderBy: '-created_at', emailAddress: ['user@example.com'], }); // Create a new user const newUser = await clerkClient.users.createUser({ emailAddress: ['newuser@example.com'], password: 'securePassword123', firstName: 'John', lastName: 'Doe', publicMetadata: { role: 'customer' }, }); // Update user metadata await clerkClient.users.updateUserMetadata('user_123', { publicMetadata: { subscription: 'pro' }, privateMetadata: { stripeCustomerId: 'cus_xxx' }, }); // Ban/unban a user await clerkClient.users.banUser('user_123'); await clerkClient.users.unbanUser('user_123'); // Delete a user await clerkClient.users.deleteUser('user_123'); ``` --- ## Organization Management (Backend API) Backend API methods for managing organizations, memberships, invitations, and domains programmatically. ```typescript import { clerkClient } from '@clerk/nextjs/server'; // Create an organization const org = await clerkClient.organizations.createOrganization({ name: 'Acme Corp', slug: 'acme-corp', createdBy: 'user_123', // User who becomes admin maxAllowedMemberships: 100, publicMetadata: { plan: 'enterprise' }, }); // Get organization by ID or slug const organization = await clerkClient.organizations.getOrganization({ organizationId: 'org_123', includeMembersCount: true, }); // List organizations const { data: orgs } = await clerkClient.organizations.getOrganizationList({ limit: 10, query: 'acme', orderBy: '-created_at', }); // Manage memberships const membership = await clerkClient.organizations.createOrganizationMembership({ organizationId: 'org_123', userId: 'user_456', role: 'org:member', }); await clerkClient.organizations.updateOrganizationMembership({ organizationId: 'org_123', userId: 'user_456', role: 'org:admin', }); // List members const { data: members } = await clerkClient.organizations.getOrganizationMembershipList({ organizationId: 'org_123', limit: 50, role: ['org:admin'], }); // Send invitation const invitation = await clerkClient.organizations.createOrganizationInvitation({ organizationId: 'org_123', emailAddress: 'invite@example.com', role: 'org:member', inviterUserId: 'user_123', redirectUrl: 'https://myapp.com/accept-invite', }); // Revoke invitation await clerkClient.organizations.revokeOrganizationInvitation({ organizationId: 'org_123', invitationId: 'orginv_123', }); ``` --- ## Session Management (Backend API) Backend API methods for managing user sessions, including listing, revoking, and verifying sessions. ```typescript import { clerkClient } from '@clerk/nextjs/server'; // List all sessions for a user const { data: sessions } = await clerkClient.sessions.getSessionList({ userId: 'user_123', }); // Get a specific session const session = await clerkClient.sessions.getSession('sess_123'); // Revoke a session (sign out) await clerkClient.sessions.revokeSession('sess_123'); // Verify a session token import { verifyToken } from '@clerk/backend'; const verified = await verifyToken(sessionToken, { secretKey: process.env.CLERK_SECRET_KEY, authorizedParties: ['https://myapp.com'], }); console.log(verified.sub); // User ID console.log(verified.sid); // Session ID ``` --- ## verifyWebhook (Webhook Verification) The `verifyWebhook()` function verifies the authenticity of incoming Clerk webhooks using Svix signatures, ensuring webhook payloads haven't been tampered with. ```typescript // app/api/webhooks/clerk/route.ts import { verifyWebhook } from '@clerk/nextjs/webhooks'; import type { WebhookEvent } from '@clerk/nextjs/webhooks'; export async function POST(req: Request) { try { const evt = await verifyWebhook(req); // Handle different event types switch (evt.type) { case 'user.created': const { id, email_addresses, first_name } = evt.data; console.log(`New user: ${id}, ${email_addresses[0]?.email_address}`); // Create user in your database await db.user.create({ data: { clerkId: id, email: email_addresses[0]?.email_address, name: first_name, }, }); break; case 'user.updated': await db.user.update({ where: { clerkId: evt.data.id }, data: { name: evt.data.first_name }, }); break; case 'user.deleted': await db.user.delete({ where: { clerkId: evt.data.id }, }); break; case 'organization.created': console.log(`New org: ${evt.data.name}`); break; case 'organizationMembership.created': console.log(`User ${evt.data.public_user_data.user_id} joined org`); break; case 'session.created': console.log(`New session for user ${evt.data.user_id}`); break; } return new Response('Success', { status: 200 }); } catch (err) { console.error('Webhook verification failed:', err); return new Response('Webhook verification failed', { status: 400 }); } } ``` --- ## Express Integration The `@clerk/express` package provides middleware for protecting Express routes and accessing authentication state. ```typescript import 'dotenv/config'; import express from 'express'; import { clerkMiddleware, requireAuth, getAuth, clerkClient } from '@clerk/express'; const app = express(); // Apply Clerk middleware globally app.use(clerkMiddleware()); // Public route app.get('/', (req, res) => { res.json({ message: 'Welcome!' }); }); // Protected route using requireAuth middleware app.get('/protected', requireAuth(), (req, res) => { const { userId, sessionId } = getAuth(req); res.json({ message: 'Protected data', userId, sessionId }); }); // Check permissions app.get('/admin', requireAuth(), (req, res) => { const auth = getAuth(req); if (!auth.has({ role: 'org:admin' })) { return res.status(403).json({ error: 'Forbidden' }); } res.json({ message: 'Admin data' }); }); // Use backend API app.get('/users', requireAuth(), async (req, res) => { const users = await clerkClient.users.getUserList({ limit: 10 }); res.json({ users: users.data }); }); // Custom sign-in redirect app.get('/dashboard', requireAuth({ signInUrl: '/login' }), (req, res) => { res.json({ message: 'Dashboard' }); }); app.listen(3000, () => console.log('Server running on port 3000')); ``` --- ## useSignIn and useSignUp Hooks Hooks for building custom sign-in and sign-up flows with full control over the authentication process. ```tsx 'use client'; import { useSignIn, useSignUp } from '@clerk/nextjs'; import { useState } from 'react'; export function CustomSignIn() { const { isLoaded, signIn, setActive } = useSignIn(); const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); const [error, setError] = useState(''); if (!isLoaded) return null; const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); try { const result = await signIn.create({ identifier: email, password, }); if (result.status === 'complete') { await setActive({ session: result.createdSessionId }); window.location.href = '/dashboard'; } else if (result.status === 'needs_second_factor') { // Handle 2FA } } catch (err: any) { setError(err.errors?.[0]?.message || 'Sign in failed'); } }; // OAuth sign-in const signInWithGoogle = () => { signIn.authenticateWithRedirect({ strategy: 'oauth_google', redirectUrl: '/sso-callback', redirectUrlComplete: '/dashboard', }); }; return ( <form onSubmit={handleSubmit}> <input type="email" value={email} onChange={(e) => setEmail(e.target.value)} placeholder="Email" /> <input type="password" value={password} onChange={(e) => setPassword(e.target.value)} placeholder="Password" /> {error && <p className="error">{error}</p>} <button type="submit">Sign In</button> <button type="button" onClick={signInWithGoogle}> Sign in with Google </button> </form> ); } export function CustomSignUp() { const { isLoaded, signUp, setActive } = useSignUp(); const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); const [verifying, setVerifying] = useState(false); const [code, setCode] = useState(''); const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); if (!isLoaded) return; try { await signUp.create({ emailAddress: email, password, }); // Send verification email await signUp.prepareEmailAddressVerification({ strategy: 'email_code' }); setVerifying(true); } catch (err: any) { console.error(err.errors?.[0]?.message); } }; const handleVerification = async (e: React.FormEvent) => { e.preventDefault(); if (!isLoaded) return; try { const result = await signUp.attemptEmailAddressVerification({ code }); if (result.status === 'complete') { await setActive({ session: result.createdSessionId }); window.location.href = '/welcome'; } } catch (err: any) { console.error(err.errors?.[0]?.message); } }; if (verifying) { return ( <form onSubmit={handleVerification}> <input value={code} onChange={(e) => setCode(e.target.value)} placeholder="Verification code" /> <button type="submit">Verify</button> </form> ); } return ( <form onSubmit={handleSubmit}> <input type="email" value={email} onChange={(e) => setEmail(e.target.value)} placeholder="Email" /> <input type="password" value={password} onChange={(e) => setPassword(e.target.value)} placeholder="Password" /> <button type="submit">Sign Up</button> </form> ); } ``` --- ## Protect and Show Components Control components for conditionally rendering content based on authentication state and permissions. ```tsx import { SignedIn, SignedOut, Protect, RedirectToSignIn } from '@clerk/nextjs'; export default function ConditionalContent() { return ( <div> {/* Show only when signed in */} <SignedIn> <p>Welcome back! You are signed in.</p> <UserButton /> </SignedIn> {/* Show only when signed out */} <SignedOut> <p>Please sign in to continue.</p> <SignInButton mode="modal"> <button>Sign In</button> </SignInButton> </SignedOut> {/* Protect with role */} <Protect role="org:admin" fallback={<p>Admin access required</p>}> <AdminDashboard /> </Protect> {/* Protect with permission */} <Protect permission="org:billing:manage" fallback={<p>You don't have billing access</p>} > <BillingSettings /> </Protect> {/* Protect with custom condition */} <Protect condition={(has) => has({ role: 'org:admin' }) || has({ role: 'org:billing_manager' })} fallback={<p>Access denied</p>} > <SensitiveContent /> </Protect> {/* Redirect if not authenticated */} <SignedOut> <RedirectToSignIn /> </SignedOut> </div> ); } ``` --- ## Testing with @clerk/testing The `@clerk/testing` package provides utilities for testing Clerk-authenticated applications with Playwright and Cypress. ```typescript // Playwright setup - playwright.config.ts import { clerkSetup } from '@clerk/testing/playwright'; import { defineConfig } from '@playwright/test'; export default defineConfig({ globalSetup: clerkSetup, use: { baseURL: 'http://localhost:3000', }, }); // Playwright test - tests/auth.spec.ts import { test, expect } from '@playwright/test'; import { clerk, setupClerkTestingToken } from '@clerk/testing/playwright'; test.beforeEach(async ({ page }) => { await setupClerkTestingToken({ page }); }); test('authenticated user can access dashboard', async ({ page }) => { await clerk.signIn({ page, signInParams: { strategy: 'password', identifier: 'test@example.com', password: 'testpassword123', }, }); await page.goto('/dashboard'); await expect(page.getByText('Welcome')).toBeVisible(); }); test('signed out user is redirected', async ({ page }) => { await clerk.signOut({ page }); await page.goto('/dashboard'); await expect(page).toHaveURL(/sign-in/); }); // Cypress setup - cypress/support/e2e.ts import { addClerkCommands } from '@clerk/testing/cypress'; addClerkCommands({ Cypress, cy }); // Cypress test - cypress/e2e/auth.cy.ts describe('Authentication', () => { beforeEach(() => { cy.clerkSignIn({ strategy: 'password', identifier: 'test@example.com', password: 'testpassword123', }); }); it('shows dashboard for authenticated users', () => { cy.visit('/dashboard'); cy.contains('Welcome').should('be.visible'); }); afterEach(() => { cy.clerkSignOut(); }); }); ``` --- Clerk provides a comprehensive solution for adding authentication to JavaScript applications across multiple frameworks. The primary use cases include implementing sign-in/sign-up flows with pre-built UI components, protecting API routes and pages, managing users and organizations programmatically through the backend API, and handling authentication-related webhooks. The SDK's modular architecture allows developers to use only the packages they need while maintaining consistent APIs across different frameworks. For integration patterns, Next.js applications typically use `clerkMiddleware()` for route protection and `auth()` for server-side authentication checks, while React applications rely on hooks like `useAuth()` and `useUser()` for client-side state. Backend services can use `createClerkClient()` directly for user management operations. The webhook system enables real-time synchronization between Clerk and your application's database, making it ideal for keeping user data in sync across systems. Multi-tenant applications benefit from the organization features, which provide built-in role-based access control and membership management.