Clerk
clerkAuth38 lines
Drop-in authentication with prebuilt sign-in, MFA and user management.
Current — as published in v1.3.2. Written by hand for Clerk, not generated.
The rule
Reading auth state
tsx
const { isLoaded, isSignedIn, userId } = useAuth();
if (!isLoaded) return <Splash />;Never treat "not loaded" as "signed out". Doing so flashes the sign-in screen at every launch for users who are already authenticated, and can redirect them out of a deep link.
Tokens
tokenCachemust be backed byexpo-secure-store. A session token is a credential;AsyncStorageis plaintext.- Send
await getToken()as a bearer token to your backend. - The backend verifies the token. Never trust a user id from a request body or a query parameter.
- The Clerk secret key is server-side only, never in the app.
User data
- Store Clerk's
userIdon your own rows to join user data. - Handle the
user.deletedwebhook so removing a user removes their data. Orphaned personal data is a compliance problem, not just untidiness.
Environments
- Separate Clerk applications for development and production. Sharing one puts test accounts in your production user pool.
Never
- Never log a session token or JWT.
- Never gate access purely on client state — the backend re-verifies.
- Never render user-specific UI before
isLoaded.
As each tool receives it
The same guidance, in the shape each editor reads. Cursor and Claude Code are written separately by hand; the rest are derived from the Cursor rule.
.cursor/rules/clerk.mdc
---
description: Clerk authentication conventions
globs: ["src/features/auth/**", "src/services/**", "app/**"]
alwaysApply: false
---
# Clerk
## Reading auth state
```tsx
const { isLoaded, isSignedIn, userId } = useAuth();
if (!isLoaded) return <Splash />;
```
Never treat "not loaded" as "signed out". Doing so flashes the sign-in screen at
every launch for users who are already authenticated, and can redirect them out
of a deep link.
## Tokens
- `tokenCache` must be backed by `expo-secure-store`. A session token is a
credential; `AsyncStorage` is plaintext.
- Send `await getToken()` as a bearer token to your backend.
- The backend **verifies** the token. Never trust a user id from a request body
or a query parameter.
- The Clerk secret key is server-side only, never in the app.
## User data
- Store Clerk's `userId` on your own rows to join user data.
- Handle the `user.deleted` webhook so removing a user removes their data.
Orphaned personal data is a compliance problem, not just untidiness.
## Environments
- Separate Clerk applications for development and production. Sharing one puts
test accounts in your production user pool.
## Never
- Never log a session token or JWT.
- Never gate access purely on client state — the backend re-verifies.
- Never render user-specific UI before `isLoaded`.
What else this module writes
Selecting Clerk contributes more than a rule file — all of it merged with every other module you pick, with conflicts resolved rather than duplicated.
Environment
EXPO_PUBLIC_CLERK_PUBLISHABLE_KEYrequiredPublishable key for this environment's Clerk instance.CLERK_SECRET_KEYoptionalServer-side key for backend verification and the admin API. Never ship in the app.CLERK_WEBHOOK_SECREToptionalVerifies incoming webhooks, including `user.deleted`. Server-side only.Dependencies
@clerk/clerk-expo^2.19.0expo-secure-store^57.0.0
Folders
src/features/auth/screens/src/features/auth/components/src/hooks/auth/
Related
Put this in your repo
Adds Clerk to a project this tool generated, without starting over. Files you have hand-edited are left alone.