Clerk

Drop-in authentication with prebuilt sign-in, MFA and user management.

adds it to an existing project · no account needed
Currentas published in v1.5.1
This rule adapts to the rest of your stack. The text below is shown for a project that selected the companion module; a different selection changes a sentence or two.

The rule

This is the whole text, exactly as your agent receives it. Nothing is held back for the paid tier.

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.

6 formats, one per tool

Each tab is the file that tool actually reads, at the path it actually looks in. Knowing where each one looks is most of the work of supporting it.

.cursor/rules/clerk.mdchand-written
---
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`.

Hand-written by the module author, frontmatter and all. It is the source the four derived formats are rendered from, so a correction lands here first.

What else this module writes

The rule is one file of several. Selecting Clerk contributes all of this too — merged with every other module you pick, with conflicts resolved rather than duplicated.

Environment
{{envPrefix}}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
Depends on the rest of the stack — this module installs different packages depending on what else you select, so there is no single list to show.
Folders
src/features/auth/screens/src/features/auth/components/src/hooks/auth/

Advisory history

Every time this rule turned out to be wrong, and what we did about it.

No corrections yet

This rule has been accurate since it was published. That is a fact about the rule, not a promise about the future — which is the whole reason this section exists.

Pro tells you the day a correction lands that affects a repo you actually have.

See what Pro adds →

Rules people add alongside this one

Put this rule in a real project

The wizard picks the rest of the stack with you, writes all 6 formats, and leaves a manifest so check can tell you when any of it drifts.