Try Live
Add Docs
Rankings
Pricing
Docs
Install
Theme
Install
Docs
Pricing
More...
More...
Try Live
Rankings
Enterprise
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:
70,998
Snippets:
681
Trust Score:
8.4
Update:
3 months ago
Context
Skills
Chat
Benchmark
76.5
Suggestions
Latest
Show doc for...
Code
Info
Show Results
Context Summary (auto-generated)
Raw
Copy
Link
# Clerk JavaScript SDK Clerk is a comprehensive authentication and user management platform designed to streamline the integration of secure authentication flows into JavaScript and web applications. It provides a complete solution for implementing sign-up, sign-in, user profiles, multi-factor authentication, social logins, and organization management across multiple frameworks and runtime environments. The platform abstracts away the complexity of authentication infrastructure, allowing developers to focus on building their core application features. This monorepo contains the official Clerk JavaScript SDKs under the `@clerk` namespace, supporting a wide range of environments including web browsers, Node.js servers, React applications, Next.js projects, Express backends, and mobile applications via React Native and Expo. Each package is purpose-built for its target environment while maintaining a consistent API design and security model. The SDK handles session management, JWT token validation, middleware integration, and provides both pre-built UI components and low-level APIs for custom authentication flows. ## Installation and Setup Installing Clerk in a Next.js application ```bash npm install @clerk/nextjs # or pnpm add @clerk/nextjs ``` ```typescript // app/layout.tsx import { ClerkProvider } from '@clerk/nextjs'; import './globals.css'; export default function RootLayout({ children }: { children: React.ReactNode }) { return ( <ClerkProvider> <html lang="en"> <body>{children}</body> </html> </ClerkProvider> ); } ``` ```bash # .env.local NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_... CLERK_SECRET_KEY=sk_test_... ``` ## Server-Side Authentication in Next.js Authenticating server components and retrieving user data ```typescript // app/dashboard/page.tsx import { auth, currentUser } from '@clerk/nextjs/server'; import { redirect } from 'next/navigation'; export default async function DashboardPage() { const { userId } = await auth(); // Redirect to sign-in if not authenticated if (!userId) { redirect('/sign-in'); } // Get full user object const user = await currentUser(); return ( <div> <h1>Welcome, {user?.firstName}!</h1> <p>Email: {user?.emailAddresses[0]?.emailAddress}</p> <p>User ID: {userId}</p> </div> ); } ``` ## Client-Side Authentication Hook Using the useAuth hook for client-side authentication state and token management ```typescript // app/external-data/page.tsx 'use client'; import { useAuth } from '@clerk/nextjs'; export default function ExternalDataPage() { const { userId, sessionId, getToken, isLoaded, isSignedIn } = useAuth(); const fetchExternalData = async () => { const token = await getToken(); // Fetch data from an external API with authenticated token const response = await fetch('https://api.example.com/data', { headers: { Authorization: `Bearer ${token}`, }, }); return response.json(); }; if (!isLoaded) { return <div>Loading...</div>; } if (!isSignedIn) { return <div>Sign in to view this page</div>; } return ( <div> <p> Hello, {userId}! Your current active session is {sessionId}. </p> <button onClick={fetchExternalData}>Fetch Data</button> </div> ); } ``` ## Pre-built UI Components Integrating Clerk's pre-built authentication components ```typescript // app/page.tsx import { OrganizationSwitcher, SignedIn, SignedOut, SignIn, UserButton } from '@clerk/nextjs'; import { auth, clerkClient, currentUser } from '@clerk/nextjs/server'; import Link from 'next/link'; export default async function Page() { const { userId } = await auth(); const currentUser_ = await currentUser(); const user = userId ? await (await clerkClient()).users.getUser(userId) : null; return ( <main> <ul> <li> <Link href={'/app-dir/sign-in'}>Sign in page</Link> </li> <li> <Link href={'/app-dir/sign-up'}>Sign up page</Link> </li> <li> <Link href={'/user'}>User profile page</Link> </li> </ul> <div> <h1>Hello, Next.js!</h1> {userId ? <h3>Signed in as: {userId}</h3> : <h3>Signed out</h3>} <SignedIn> <UserButton userProfileMode='navigation' userProfileUrl='/app-dir/user' /> <OrganizationSwitcher organizationProfileUrl='/app-dir/organization' createOrganizationUrl='/app-dir/create-organization' organizationProfileMode={'navigation'} createOrganizationMode={'navigation'} /> <div>{JSON.stringify(user)}</div> <div>{JSON.stringify(currentUser_)}</div> </SignedIn> <SignedOut> <SignIn routing='hash' /> </SignedOut> </div> </main> ); } ``` ## Backend API Client Creating and using the Clerk backend client for server-side operations ```typescript // lib/clerk.ts import { createClerkClient } from '@clerk/backend'; const clerk = createClerkClient({ secretKey: process.env.CLERK_SECRET_KEY, publishableKey: process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY, }); // Verify a JWT token const verifyUserToken = async (token: string) => { try { const verified = await clerk.verifyToken(token); return verified; } catch (error) { console.error('Token verification failed:', error); return null; } }; // Get user by ID const getUserById = async (userId: string) => { try { const user = await clerk.users.getUser(userId); return user; } catch (error) { console.error('Failed to fetch user:', error); return null; } }; // Update user metadata const updateUserMetadata = async (userId: string, metadata: Record<string, any>) => { try { const user = await clerk.users.updateUserMetadata(userId, { publicMetadata: metadata, }); return user; } catch (error) { console.error('Failed to update user metadata:', error); return null; } }; // List all users with pagination const listUsers = async (limit = 10, offset = 0) => { try { const users = await clerk.users.getUserList({ limit, offset }); return users; } catch (error) { console.error('Failed to list users:', error); return []; } }; export { clerk, verifyUserToken, getUserById, updateUserMetadata, listUsers }; ``` ## Express.js Middleware Integration Setting up Clerk authentication in an Express application ```typescript // server.ts import type { Application, Request, Response, NextFunction } from 'express'; import { clerkMiddleware } from '@clerk/express'; import * as express from 'express'; import { privateRoutes, publicRoutes } from './routes'; const port = process.env.PORT || 3000; const app: Application = express(); app.set('view engine', 'ejs'); app.set('views', 'src/views'); // Apply Clerk middleware globally app.use(clerkMiddleware()); app.use(publicRoutes); app.use(privateRoutes); app.use((err: Error, _req: Request, res: Response, _next: NextFunction) => { console.error(err.stack); res.status(401).send('Unauthenticated!'); }); app.listen(port, () => { console.log(`Example app listening at http://localhost:${port}`); }); ``` ## Protected Routes in Express Implementing authentication and authorization in Express routes ```typescript // routes/private.ts import { getAuth, requireAuth, UnauthorizedError, ForbiddenError } from '@clerk/express'; import { Router, Request as ExpressRequest, Response as ExpressResponse, NextFunction } from 'express'; const router = Router(); // Require authentication for all routes in this router router.use(requireAuth); // Get current authenticated user router.get('/me', async (req: ExpressRequest, res: ExpressResponse) => { return res.json({ auth: getAuth(req) }); }); // Admin-only route with role-based access control router.get('/admin-only', async (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => { const auth = getAuth(req); if (!auth.has({ role: 'admin' })) { return next(new ForbiddenError()); } return res.json({ message: 'Hello admin!', auth }); }); // Error handling for authentication errors router.use((err: Error, _req: ExpressRequest, res: ExpressResponse, next: NextFunction) => { if (err instanceof UnauthorizedError) { return res.status(401).json({ error: 'Unauthorized' }); } if (err instanceof ForbiddenError) { return res.status(403).json({ error: 'Forbidden' }); } return next(err); }); export const privateRoutes = router; ``` ## React Standalone Integration Using Clerk in a standalone React application ```bash npm install @clerk/react ``` ```typescript // App.tsx import { ClerkProvider, SignedIn, SignedOut, SignInButton, UserButton } from '@clerk/react'; function App() { return ( <ClerkProvider publishableKey={import.meta.env.VITE_CLERK_PUBLISHABLE_KEY}> <header> <SignedOut> <SignInButton /> </SignedOut> <SignedIn> <UserButton /> </SignedIn> </header> <main> <SignedIn> <ProtectedContent /> </SignedIn> <SignedOut> <PublicContent /> </SignedOut> </main> </ClerkProvider> ); } export default App; ``` ## Organization Management Managing multi-tenant organizations with role-based access control ```typescript // app/dashboard/organization/page.tsx 'use client'; import { useOrganization, useOrganizationList } from '@clerk/nextjs'; import { useEffect } from 'react'; export default function OrganizationPage() { const { organization, membership, isLoaded } = useOrganization(); const { organizationList, setActive } = useOrganizationList(); if (!isLoaded) { return <div>Loading organization...</div>; } const switchOrganization = async (orgId: string) => { await setActive({ organization: orgId }); }; return ( <div> <h1>Current Organization: {organization?.name}</h1> <p>Your role: {membership?.role}</p> <h2>Switch Organization</h2> <ul> {organizationList?.map((org) => ( <li key={org.organization.id}> <button onClick={() => switchOrganization(org.organization.id)}> {org.organization.name} </button> </li> ))} </ul> <h2>Organization Members</h2> {membership?.role === 'admin' && ( <button onClick={() => console.log('Invite member')}> Invite Member </button> )} </div> ); } ``` ## Webhook Handling Processing Clerk webhooks for user lifecycle events ```typescript // app/api/webhooks/clerk/route.ts import { Webhook } from 'svix'; import { headers } from 'next/headers'; import { WebhookEvent } from '@clerk/nextjs/server'; export async function POST(req: Request) { const WEBHOOK_SECRET = process.env.CLERK_WEBHOOK_SECRET; if (!WEBHOOK_SECRET) { throw new Error('Please add CLERK_WEBHOOK_SECRET to .env'); } // Get the headers const headerPayload = await headers(); const svix_id = headerPayload.get('svix-id'); const svix_timestamp = headerPayload.get('svix-timestamp'); const svix_signature = headerPayload.get('svix-signature'); if (!svix_id || !svix_timestamp || !svix_signature) { return new Response('Error: Missing svix headers', { status: 400 }); } const payload = await req.json(); const body = JSON.stringify(payload); // Verify the webhook const wh = new Webhook(WEBHOOK_SECRET); let evt: WebhookEvent; try { evt = wh.verify(body, { 'svix-id': svix_id, 'svix-timestamp': svix_timestamp, 'svix-signature': svix_signature, }) as WebhookEvent; } catch (err) { console.error('Error verifying webhook:', err); return new Response('Error: Verification failed', { status: 400 }); } // Handle the webhook const eventType = evt.type; if (eventType === 'user.created') { const { id, email_addresses, first_name, last_name } = evt.data; console.log(`New user created: ${id}`); // Sync user to your database // await db.user.create({ clerkId: id, email: email_addresses[0].email_address }); } if (eventType === 'user.updated') { const { id, email_addresses } = evt.data; console.log(`User updated: ${id}`); // Update user in your database } if (eventType === 'user.deleted') { const { id } = evt.data; console.log(`User deleted: ${id}`); // Delete or soft-delete user from your database } return new Response('Webhook processed successfully', { status: 200 }); } ``` ## Session Management and Token Refresh Managing sessions and handling token refresh ```typescript // lib/session-utils.ts 'use client'; import { useSession, useUser } from '@clerk/nextjs'; import { useEffect } from 'react'; export function useTokenRefresh() { const { session } = useSession(); const { user } = useUser(); useEffect(() => { if (!session) return; // Get fresh token whenever needed const refreshToken = async () => { try { const token = await session.getToken(); console.log('Token refreshed:', token); return token; } catch (error) { console.error('Failed to refresh token:', error); } }; // Optionally refresh token on mount or at intervals refreshToken(); }, [session]); return { sessionId: session?.id, userId: user?.id, lastActiveAt: session?.lastActiveAt, expireAt: session?.expireAt, }; } // Custom hook for API calls with automatic token injection export function useAuthenticatedFetch() { const { session } = useSession(); const authenticatedFetch = async (url: string, options: RequestInit = {}) => { const token = await session?.getToken(); if (!token) { throw new Error('No authentication token available'); } return fetch(url, { ...options, headers: { ...options.headers, Authorization: `Bearer ${token}`, }, }); }; return { authenticatedFetch }; } ``` ## Summary The Clerk JavaScript SDK is designed for modern web applications requiring secure, scalable authentication and user management. Primary use cases include SaaS applications with multi-tenancy support through organizations, e-commerce platforms requiring secure user accounts and payment profiles, social applications with OAuth integrations, enterprise applications with role-based access control and SSO, and mobile applications built with React Native or Expo. The SDK handles complex authentication scenarios including passwordless login, multi-factor authentication, email/SMS verification, and social login providers (Google, GitHub, Facebook, Apple, and more). Integration patterns follow framework-specific best practices: Next.js applications use the App Router with server components for authentication checks and middleware for route protection; React applications leverage hooks and context providers for authentication state management; Express and Node.js backends use middleware for request authentication and the backend client for user management operations; and webhook endpoints process user lifecycle events for database synchronization. The SDK provides both high-level abstractions through pre-built UI components and low-level APIs for custom authentication flows, making it suitable for both rapid prototyping and production applications with complex requirements. All packages follow semantic versioning and maintain backward compatibility, with automatic code migrations available for major version upgrades.