The Clerk webhook links a new signup to a pre-created client record by matching email before creating anything
The Clerk webhook at api/webhooks/clerk/route.ts handles user.created with two paths, not one. When a new user signs up through Clerk, the webhook extracts their primary email and runs prisma.client.findUnique with where email equals that address. If a record exists and its clerkId is null, the webhook updates it — linking the existing client to the new Clerk account and keeping the name James already set in the admin panel. If no email match exists, it falls through to prisma.client.upsert on clerkId instead, creating a fresh record. The two-path logic solves a sequencing problem. James creates client records in the admin panel before the client has signed up. The admin sets their name, email, and company. Then the client receives a portal invite link and creates a Clerk account. At that moment the webhook fires. Without the email pre-check, the upsert on clerkId would create a second client record — one from the admin, one from Clerk — and the client would see an empty portal with no projects. The email match bridges the gap. The name preservation matters too. The update uses existing.name or name, so if James typed Sarah Chen in the admin panel and the Clerk signup came through as sarah chen, the admin version wins. The user.updated handler is simpler — a single prisma.client.update on clerkId with conditional spread for email and name. It silently catches errors because the client might not exist yet if they update their Clerk profile before the user.created webhook arrives. Two events, two strategies, one bridging query, and the client sees their projects the moment they first log in.
Comments coming soon
Sign in with TikTok to leave a comment. Coming soon.