Guild

Ops — Clerk Keys

Clerk provides authentication (magic link / email code sign-in). Two keys are used:

Clerk provides authentication (magic link / email code sign-in). Two keys are used:

VariableWhere it livesNotes
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEYBrowser (public)Safe to expose; used by the frontend ClerkProvider
CLERK_SECRET_KEYServer onlyNever expose or commit

Both are set in .env.local for local dev and in the Cloudflare Pages dashboard for production (deploys.md).

The official rotation path: clerk env pull

The Clerk CLI (clerk, installed at /opt/homebrew/bin/clerk; verified v3.0.0, 2026-08-06) pulls your instance's keys into the local env file — this is the documented mechanism for rotating/refreshing keys:

# Pull the dev instance keys into .env.local (default)
clerk env pull
 
# Target a specific app by ID, or pull production keys to a different file
clerk env pull --app app_abc123
clerk env pull --instance prod --file .env

clerk env pull writes NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY and CLERK_SECRET_KEY (and any other Clerk-managed vars). It overwrites the target file, so don't point it at .env.local carelessly if that file carries non-Clerk vars — either merge by hand after, or pull to a scratch file and copy the two key lines over. Never commit the result.

Rotating keys end-to-end

  1. In the Clerk dashboard (dashboard.clerk.com → API Keys), rotate the secret key (or switch to a different instance, e.g. production for pass 13).
  2. Pull locally: clerk env pull (or the --instance prod / --app variants) and update .env.local.
  3. Restart npm run dev; verify sign-in still works.
  4. Update the Cloudflare Pages dashboard env vars for the same key pair (Dashboard → Workers & Pages → guild → Settings → Environment variables), then re-deploy (deploys.md).
  5. Confirm the middleware key check doesn't trip: middleware.ts throws at runtime (not build time) if either key is missing — a missing key surfaces as a clear error naming the variable.

Requirements on the instance

  • Email sign-in (magic link / email code) must be enabled on the instance — that's the platform's only sign-in method (pass 10 human step; the sign-in page renders Clerk's <SignIn />).
  • The Clerk user_… id is not the UUID stored in practitioners.user_id — the auth shim's auth.users bridge maps clerk_id → UUID on first request (lib/auth/helpers.ts::resolveUserId). Don't try to correlate the two directly; use the bridge.

On this page