Skip to main content

Command Palette

Search for a command to run...

How to Set Up Clerk Authentication with Convex in a Next.js Project

Updated
4 min read
How to Set Up Clerk Authentication with Convex in a Next.js Project
D

Javascript Engineer, Fashion Lover.

Integrating authentication shouldn't feel like a chore. By combining Clerk (for identity management) and Convex (for your backend/database), you get a powerhouse stack that handles user sessions, data synchronization, and security with minimal overhead.

This guide walks you through the end-to-end setup to get your Next.js application production-ready.

Prerequisites

Before we dive in, make sure you have the following:

  • Node.js installed on your machine.

  • A basic understanding of Next.js (App Router is recommended).

  • A fresh or existing Next.js project.

Step 1: Create a Next.js Project

If you’re starting from scratch, run the following commands in your terminal:

npx create-next-app@latest my-app cd my-app yarn run dev

Step 2: Set Up Your Clerk Account

  1. Head over to Clerk.com and create a free account.

  2. Create a new application in the Clerk Dashboard.

  3. Copy your Publishable Key and Secret Key.

  4. Create a .env.local file in your project root and add them:

NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_xxxxxxxxx CLERK_SECRET_KEY=sk_test_xxxxxxxxx

Step 3: Install Clerk

Install the Clerk Next.js SDK:

yarn install @clerk/nextjs

Step 4: Set Up Your Convex Account

  1. Go to Convex.dev and sign up.

  2. Create a new project.

Step 5: Initialize Convex in Your Project

Run the following command to link your local project to the Convex backend:

yarn install convex npx convex dev

Note: This command creates a convex/ folder and generates development keys, which are automatically added to your .env.local file. You should see a variable like:

NEXT_PUBLIC_CONVEX_URL=https://example-123.convex.cloud.

Step 6: Create a Global Providers File

To make authentication state available throughout your app, create a providers.tsx (or .jsx) file in your app directory.

Install Required Dependencies

yarn install convex && yarn install convex @clerk/nextjs

Providers Implementation

"use client";

import { ClerkProvider, useAuth } from "@clerk/nextjs"; import { ConvexProviderWithClerk } from "convex/react-clerk"; import { ConvexReactClient } from "convex/react";

const convex = new ConvexReactClient( process.env.NEXT_PUBLIC_CONVEX_URL! );

export function Providers({children,}: {children: React.ReactNode;}) { return ( <ClerkProvider> <ConvexProviderWithClerk client={convex} useAuth={useAuth}> {children} </ConvexProviderWithClerk> </ClerkProvider> ); }

Step 7: Wrap Your Application

In your app/layout.tsx, wrap the children with the Providers component you just created.

import { Providers } from "./providers";

export default function RootLayout({children,}: {children: React.ReactNode;}) { return ( <html lang="en"> <body> <Providers>{children}</Providers> </body> </html> ); }

Step 8: Configure Webhooks for User Sync

To keep your Convex database in sync with Clerk users, you need to set up a webhook.

  1. Open your Convex Dashboard.

  2. Go to SettingsGeneral.

  3. Copy the HTTP Actions URL (ensure it ends in .site).

    • Example: https://example-actions-222.convex.site

Step 9: Register the Webhook in Clerk

  1. Go to the Clerk DashboardWebhooks.

  2. Click Add Endpoint.

  3. Paste your Convex HTTP URL and append /clerk-users-webhook.

    • Final URL: https://example-actions-222.convex.site/clerk-users-webhook
  4. Select the events you want to listen to (e.g., user.created, user.updated, session.created).

Step 10: Secure Your Webhook

Clerk provides a Signing Secret for your webhook. Add this to your .env.local:

CLERK_WEBHOOK_SECRET=whsec_xxxxxxxxx

Step 11: Create a JWT Template in Clerk

Convex needs a specific JWT (JSON Web Token) to verify users.

  1. In Clerk, go to JWT TemplatesNew Template.

  2. Select Convex.

  3. Ensure the claims look like this:

JSON

{

"aud": "convex",

"name": "{{user.full_name}}",

"role": "{{user.public_metadata}}",

"email": "{{user.primary_email_address}}",

"picture": "{{user.image_url}}",

"nickname": "{{user.username}}",

"given_name": "{{user.first_name}}",

"updated_at": "{{user.updated_at}}",

"family_name": "{{user.last_name}}",

"phone_number": "{{user.primary_phone_number}}"

}

  1. Save the template.

Step 12: Copy the Issuer URL

Copy the Issuer URL from the template you just created and add it to .env.local:

NEXT_PUBLIC_CLERK_FRONTEND_API_URL=https://your-app-name.clerk.accounts.dev

Step 13: Create auth.config.js

In the root of your project, create auth.config.js. This tells Convex how to validate the Clerk tokens.

export default {providers: [{ domain: process.env.NEXT_PUBLIC_CLERK_FRONTEND_API_URL, applicationID: "convex", }]};

Step 14: Final Production Prep

Before going live, ensure your production environment variables are set:

  1. Copy all values from .env.local.

  2. Paste them into the Environment Variables section of both your Clerk and Convex production dashboards.

You now have a fully functional, secure authentication flow. Users can sign in via Clerk, and their identity is automatically verified by Convex via JWT.

Don't forget to setup your Convex Schema and have a happy development!