Skip to main content
← All notes
Building

Client records exist before the client signs up

software

When I take on a new client, the first thing I do is create their record in the admin panel. Name, email, optional company, optional Stripe customer ID. That is four fields and a submit button. No invitation email fires. No magic link gets sent. The client record sits in the database with a null clerkId, which means the notification guard — the check that prevents emails from going out — stays closed. No session notes emails, no milestone updates, no deliverable alerts. The record is just a placeholder that says this person exists and this is their email. When the client eventually signs up through the Clerk-powered sign-in page, a webhook fires. The Clerk user.created event hits the webhook endpoint. The handler checks whether a client with that email already exists in the database. If it does and the clerkId field is null, it links the two together — one update query that writes the Clerk ID onto the existing record. From that moment forward, the client can log in and see their projects, and the notification guard opens because clerkId is no longer null. If the client signs up before I create their record — maybe they find the sign-in page on their own — the webhook creates a fresh client record with their Clerk ID already attached. Either order works. Admin first, client first, it does not matter. The upsert handles both paths. The same webhook also handles user.updated events. If a client changes their email or name in Clerk, the database stays in sync automatically. One webhook route, two event types, zero manual data entry after the initial setup.

Comments coming soon

Sign in with TikTok to leave a comment. Coming soon.