Probably some stuff missing, but this will get you 90% of the way there
.env.local
and in Convex cloud)CONVEX_DEPLOYMENT=
PUBLIC_CONVEX_URL=
PUBLIC_CLERK_FRONTEND_API_URL=
PUBLIC_CLERK_PUBLISHABLE_KEY=
CLERK_SECRET_KEY=
CLERK_WEBHOOK_SECRET=
CLERK_JWT_ISSUER_DOMAIN=
Create Convex and Clerk projects.
Clerk → JWT Templates: create using Convex preset, name it convex
.
Clerk → Sessions → Custom claims: add
{
"roles": "{{user.public_metadata.roles}}",
"fullname": "{{user.full_name}}",
"lastname": "{{user.last_name}}",
"username": "{{user.username}}",
"firstname": "{{user.first_name}}"
}
Clerk → Webhooks: subscribe to user.created
, user.updated
, user.deleted
.
https://<your-convex>.convex.site/clerk-users-webhook
(or local Convex dev URL + /clerk-users-webhook
).CLERK_WEBHOOK_SECRET
(local + Convex cloud).Set env vars (see list above).
CLERK_JWT_ISSUER_DOMAIN
: your Clerk issuer (e.g. https://<app>.clerk.accounts.dev
).Optional: set user roles in Clerk unsafe_metadata
:
{ "roles": ["admin"] }
Import sample data:
npx convex import --table tasks sampleData.jsonl
Run Convex dev:
npx convex dev
Run app:
npm run dev -- --open
Notes:
/clerk-users-webhook
(see src/convex/http.ts
).src/convex/auth.config.ts
(applicationID: "convex"
).