Clerk
clerk.dev v0.1.0
Clerk SDK code examples
From the developer
Listing not observed in the last 24 hours. Check collection status.
Not specified in the available declarations: capabilities, limitations, pricing & account requirements.
Sources & dates
Developer declarations; not independently tested. Listing last checked Oct 10, 2026. Package observed Oct 10, 2026.
Description
From the marketplace listing
Clerk helps developers find SDK code examples for authentication, sign-in and sign-up, organizations, access control, and billing integration. Browse the available examples by tag or retrieve individual snippets and curated bundles for common application workflows.
Language: English · Automatically detected from descriptions.
Matches for “develop app”
Exact text from the indicated source. A mention alone does not establish support for your task.
Publisher description
Clerk helps developers find SDK code examples for authentication, sign-in and sign-up, organizations, access control, and billing integration. Browse the available examples by tag or retrieve individual snippets and curated bundles for common application workflows.
Package name
app-6a9a3c1cd0108191807da33c4cd319ed
Changes
No changes recorded yet. Follow this plugin to keep track of future changes.
First seen Sep 30, 2026. Last seen Oct 10, 2026.
Similar plugins
Find competitors to follow as you develop your plugin.
-
Search Softhills 3D/2D SDK docs for exact API signatures
Shared terms: sdk, developer, retrieve, code
-
Skills-only bundle for scoped software implementation and independent code verification in Codex.
Shared terms: code, bundle, control
-
Search PayU's official documentation, browse the payment integration catalog by platform and language, and fetch production-ready code sn...
Shared terms: code, browse, integration, snippet
-
Search Microsoft's Fluent UI System Icons by meaning and get exact @fluentui/react-icons component names and code, instead of guessing.
Shared terms: code, billing, sign, find
-
Includes the AWS MCP Server configuration and default skills for common AWS workflows. Covered domains include service selection, infrast...
Shared terms: billing, common, developer, sdk
Files & skills
File archives
Skill instructions
clerk5.99 KB
--- name: clerk description: Clerk authentication router. Use when user asks about Clerk CLI operations, adding authentication, setting up Clerk, custom sign-in flows, Swift or native iOS auth, native Android auth, Next.js patterns, React patterns, Vue patterns, Nuxt patterns, Astro patterns, TanStack Start patterns, Expo patterns, React Router patterns, Chrome Extension patterns, organizations, billing, subscriptions, payments, pricing, plans, seat-based pricing, feature entitlements, syncing users, testing, impersonating a user, or testing webhooks locally. Automatically routes to the specific skill based on their task. license: MIT metadata: version: 2.0.0 --- # Clerk Skills Router ## Version Detection Check `package.json` to determine the Clerk SDK version. This determines which patterns to use: | Package | Core 2 (LTS until Jan 2027) | Current | |---------|----------------------------|---------| | `@clerk/nextjs` | v5–v6 | v7+ | | `@clerk/react` or `@clerk/clerk-react` | v5–v6 | v7+ | | `@clerk/expo` or `@clerk/clerk-expo` | v1–v2 | v3+ | | `@clerk/react-router` | v1–v2 | v3+ | | `@clerk/tanstack-react-start` | < v0.26.0 | v0.26.0+ | **Default to current** if the version is unclear or the project is new. Core 2 packages use `@clerk/clerk-react` and `@clerk/clerk-expo` (with `clerk-` prefix); current packages use `@clerk/react` and `@clerk/expo`. All skills are written for the current SDK. When something differs in Core 2, it's noted inline with `> **Core 2 ONLY (skip if current SDK):**` callouts. The exception is `clerk-custom-ui`, which has separate `core-2/` and `core-3/` directories for custom flow hooks since those APIs are entirely different between versions. --- ## By Task **Adding Clerk to your project** → Use `clerk-setup` - Framework detection and quickstart - Environment setup, API keys, temporary dev keys via `clerk init` - Migration from other auth providers **Operating Clerk from the CLI** → Use `clerk-cli` - Auth, linking, `doctor`, and environment pulls - User, org, session, app, and instance management - Impersonating a user (`clerk impersonate`) and local webhook testing (`clerk webhooks listen`) - Feature toggles (`clerk enable orgs`, `clerk enable billing`) - Backend, Platform, and Frontend API calls through `clerk api` - Deploy handoff and deploy status verification **Custom sign-in/sign-up UI** → Use `clerk-custom-ui` - Custom authentication flows with `useSignIn` / `useSignUp` hooks - Appearance and styling (themes, colors, layout) - `<Show>` component for conditional rendering **Advanced Next.js patterns** → Use `clerk-nextjs-patterns` - Server vs Client auth APIs - Middleware strategies - Server Actions, caching - API route protection **React patterns** → Use `clerk-react-patterns` - Hooks (`useAuth`, `useUser`, `useClerk`) - Protected routes, auth guards - Router integration **React Router patterns** → Use `clerk-react-router-patterns` - Loaders & actions with auth - Route protection - SSR auth **Vue patterns** → Use `clerk-vue-patterns` - Composables (`useAuth`, `useUser`, `useClerk`) - Vue Router guards - Pinia auth store integration **Nuxt patterns** → Use `clerk-nuxt-patterns` - Server middleware auth - SSR auth with composables - Server API routes **Astro patterns** → Use `clerk-astro-patterns` - SSR auth pages - Island components with React - Middleware & API routes **TanStack Start patterns** → Use `clerk-tanstack-patterns` - Server functions with auth - Route protection via loaders - Vinxi server integration **Expo / React Native auth** → Use `clerk-expo` - Prebuilt native components (AuthView, UserButton) - Custom flows: email, password, SMS/phone OTP, MFA - OAuth/SSO and native Google/Apple sign-in - Expo Router protected routes, token storage, push notifications **Chrome Extension patterns** → Use `clerk-chrome-extension-patterns` - Background scripts auth - Popup auth flows - Content scripts with sync host **B2B / Organizations** → Use `clerk-orgs`
Preview of the first 4,000 characters. Read full instructions →
clerk-android8.37 KB
---
name: clerk-android
description: Implement Clerk authentication for native Android apps using Kotlin and
Jetpack Compose with clerk-android source-guided patterns. Use for prebuilt AuthView/UserButton
or custom API-driven auth flows. Do not use for Expo or React Native projects.
license: MIT
allowed-tools: WebFetch
metadata:
author: clerk
version: 1.2.0
compatibility: Requires Android Studio and clerk-android Gradle dependency
---
# Clerk Android (Native)
This skill implements Clerk in native Android projects by following current `clerk-android` SDK and docs patterns.
## Activation Rules
Activate this skill when either condition is true:
- The user explicitly asks for Android, Kotlin, Jetpack Compose, or native mobile Clerk implementation on Android.
- The project appears to be native Android (for example `build.gradle(.kts)` with Android plugins, `AndroidManifest.xml`, `app/src/main/java`, Compose UI files).
Do not activate this skill when either condition is true:
- The project is Expo.
- The project is React Native.
If Expo/React Native signals are present, route to the general setup skill instead.
## What Do You Need?
| Task | Reference |
|------|-----------|
| Prebuilt AuthView / UserButton (fastest) | references/prebuilt.md |
| Custom API-driven auth flows (full control) | references/custom.md |
## Quick Start
| Step | Action |
|------|--------|
| 1 | Confirm project type is native Android and not Expo/React Native |
| 2 | Determine flow type (`prebuilt` or `custom`) and load the matching reference file |
| 3 | Ensure a real Clerk publishable key exists (or ask developer) |
| 4 | Ensure correct Clerk artifacts are installed for the selected flow |
| 5 | Read official Android quickstart and verify required setup (Native API, min SDK/Java, manifest, initialization) |
| 6 | Inspect `clerk-android` source/sample patterns relevant to selected flow |
| 7 | Implement flow by following only the selected reference checklist |
## Decision Tree
```text
User asks for Clerk in Android/Kotlin
|
+-- Expo/React Native project detected?
| |
| +-- YES -> Do not use this skill
| |
| +-- NO -> Continue
|
+-- Existing auth UI detected?
| |
| +-- Prebuilt views detected -> Load references/prebuilt.md
| |
| +-- Custom flow detected -> Load references/custom.md
| |
| +-- New implementation -> Ask developer prebuilt/custom, then load matching reference
|
+-- Ensure publishable key and SDK initialization path
|
+-- Ensure correct Android artifacts are installed
|
+-- Verify quickstart prerequisites in project
|
+-- Implement using selected flow reference
```
## Flow References
After flow type is known, load exactly one:
- Prebuilt flow: [references/prebuilt.md](references/prebuilt.md)
- Custom flow: [references/custom.md](references/custom.md)
Do not blend the two references in a single implementation unless the developer explicitly asks for a hybrid approach.
## Interaction Contract
Before any implementation edits, the agent must have both:
- flow choice: `prebuilt` or `custom`
- a real Clerk publishable key
If either value is missing from the user request/context:
- ask the user for the missing value(s)
- pause and wait for the answer
- do not edit files or install dependencies yet
Only skip asking when the user has already explicitly provided the value in this conversation.
## Source-Driven Templates
Do not hardcode implementation examples in this skill. Inspect current `clerk-android` source/docs for the installed SDK version before implementing.
| Use Case | Source of Truth |
|----------|-----------------|
| SDK artifacts and dependency split (`clerk-android-api` vs `clerk-android-ui`) | `clerk-android` README and Android install docs |
| SDK initialization and publishable key wiring | Android quickstart and `source/api/.../Clerk.kt` |
| Prebuilt auth and profile behavior | `source/Preview of the first 4,000 characters. Read full instructions →
Referenced files: 2 — file references are metadata, not package contents.
clerk-astro-patterns3.23 KB
---
name: clerk-astro-patterns
description: 'Astro patterns with Clerk — middleware, SSR pages, island components,
API routes, static vs SSR rendering. Triggers on: astro clerk, clerk astro middleware,
astro protected page, clerk island component, astro API route auth, clerk astro
SSR.'
license: MIT
allowed-tools: WebFetch
metadata:
author: clerk
version: 1.0.0
---
# Astro Patterns
SDK: `@clerk/astro` v3+. Requires Astro 4.15+.
## What Do You Need?
| Task | Reference |
|------|-----------|
| Configure middleware | references/middleware.md |
| Protect SSR pages | references/ssr-pages.md |
| Use Clerk in island components | references/island-components.md |
| Auth in API routes | references/api-routes.md |
| Use Clerk with React in Astro | references/astro-react.md |
## Mental Model
Astro has two rendering modes per page: **SSR** and **static prerender**. Clerk works differently in each:
- **SSR pages** — use `Astro.locals.auth()` which is populated by the middleware
- **Static pages** (`export const prerender = true`) — Clerk middleware skips them; use client-side hooks in islands
- **Islands** — React/Vue/Svelte components; use `useAuth()` and other hooks from `@clerk/astro/react`
```
Request → clerkMiddleware() → SSR page → Astro.locals.auth()
↓
Island (.client) → useAuth() hook
```
## Setup
### astro.config.mjs
```ts
import { defineConfig } from 'astro/config'
import clerk from '@clerk/astro'
export default defineConfig({
integrations: [clerk()],
output: 'server',
})
```
### src/middleware.ts
```ts
import { clerkMiddleware, createRouteMatcher } from '@clerk/astro/server'
const isProtectedRoute = createRouteMatcher(['/dashboard(.*)'])
export const onRequest = clerkMiddleware((auth, context, next) => {
if (isProtectedRoute(context.request) && !auth().userId) {
return auth().redirectToSignIn()
}
return next()
})
```
## SSR Page Auth
```astro
---
const { userId, orgId } = Astro.locals.auth()
if (!userId) return Astro.redirect('/sign-in')
---
<h1>Dashboard</h1>
```
## Common Pitfalls
| Symptom | Cause | Fix |
|---------|-------|-----|
| `Astro.locals.auth` is undefined | Missing middleware | Add `clerkMiddleware` to `src/middleware.ts` |
| Auth works in dev but not production | `output: 'static'` globally | Set `output: 'server'` or `hybrid` for protected pages |
| Static page has no auth | Prerendered pages skip middleware | Use `export const prerender = false` or move to island |
| Island not reactive to sign-in | Missing `client:load` directive | Add `client:load` to the island component |
## Import Map
| What | Import From |
|------|-------------|
| `clerkMiddleware`, `createRouteMatcher` | `@clerk/astro/server` |
| `useAuth`, `useUser`, `UserButton` | `@clerk/astro/react` |
| Astro components (`<SignIn>`, etc.) | `@clerk/astro/components` |
## Env Variables
```
# .env
PUBLIC_CLERK_PUBLISHABLE_KEY=pk_...
CLERK_SECRET_KEY=sk_...
```
Astro uses `PUBLIC_` prefix for client-exposed variables (not `NEXT_PUBLIC_`).
## See Also
- `clerk-setup` - Initial Clerk install
- `clerk-custom-ui` - Custom flows & appearance
- `clerk-orgs` - B2B organizations
## Docs
[Astro SDK](https://clerk.com/docs/astro/getting-started/quickstart)
Referenced files: 12 — file references are metadata, not package contents.
clerk-backend-api15.9 KB
---
name: clerk-backend-api
description: "Clerk Backend REST API explorer and executor. Browse tags, inspect endpoint schemas, and execute authenticated requests. Use when listing users, managing organizations, or calling any Clerk API endpoint."
allowed-tools: Bash, Read, Grep, Skill, WebFetch
license: MIT
compatibility: Requires CLERK_SECRET_KEY (sk_*) for Backend API calls.
---
## Options context
User Prompt: $ARGUMENTS
## CRITICAL: Mandatory checks before EVERY write request
Before ANY POST / PATCH / PUT / DELETE, you MUST do ALL of the following in your response:
1. **Check CLERK_SECRET_KEY** — verify it is set:
```bash
echo $CLERK_SECRET_KEY | head -c 10
```
If empty, stop and ask the user. Do not proceed without a valid key.
2. **Check CLERK_BAPI_SCOPES** — run:
```bash
echo $CLERK_BAPI_SCOPES
```
Inspect the output. If scopes are missing or do not include the required write permission, tell the user: *"This is a write operation and your current scopes may not allow it. Rerun with --admin to bypass?"* Do NOT attempt the request and fail — ask first.
3. **For DELETE requests:** warn explicitly that the action is **IRREVERSIBLE** and list exactly what data will be permanently destroyed (user record, all sessions, all memberships, all associated data). Require explicit confirmation before proceeding. This warning is MANDATORY — never skip it.
4. **For metadata operations:** always explain which metadata type is being used and why (see Metadata types section below).
---
## FAST PATH: Common operations (use directly, no spec fetching needed)
For the operations below, skip spec fetching and execute immediately using these exact templates. Substitute `$CLERK_SECRET_KEY`, `$USER_ID`, `$ORG_ID`, `$EMAIL` as needed from the user's context.
### Create organization + invite member (two-step)
```bash
# Step 1 — Create organization
ORG=$(curl -s -X POST "https://api.clerk.com/v1/organizations" \
-H "Authorization: Bearer $CLERK_SECRET_KEY" \
-H "Content-Type: application/json" \
-d "{\"name\": \"Acme Corp\", \"created_by\": \"$USER_ID\"}")
echo "$ORG" | python3 -c "import sys,json; d=json.load(sys.stdin); print(json.dumps(d, indent=2))"
# Step 2 — Extract org ID
ORG_ID=$(echo "$ORG" | python3 -c "import sys,json; print(json.load(sys.stdin)['id'])")
# Step 3 — Invite member with role
curl -s -X POST "https://api.clerk.com/v1/organizations/${ORG_ID}/invitations" \
-H "Authorization: Bearer $CLERK_SECRET_KEY" \
-H "Content-Type: application/json" \
-d "{\"email_address\": \"user@example.com\", \"role\": \"org:admin\"}" \
| python3 -c "import sys,json; print(json.dumps(json.load(sys.stdin), indent=2))"
```
**Roles:** use `"org:admin"` or `"org:member"` (always prefix with `org:`).
### SDK equivalent (for Next.js / TypeScript projects with `@clerk/nextjs` or `@clerk/backend`)
```typescript
import { clerkClient } from '@clerk/nextjs/server'
// OR if using @clerk/backend directly:
// import { createClerkClient } from '@clerk/backend'
// const clerkClient = createClerkClient({ secretKey: process.env.CLERK_SECRET_KEY })
// Step 1: Create organization
const org = await clerkClient.organizations.createOrganization({
name: 'Acme Corp',
createdBy: userId, // required — the ID of the user creating the org
})
// Step 2: Invite member to the org
const invitation = await clerkClient.organizations.createOrganizationInvitation({
organizationId: org.id,
emailAddress: 'user@example.com',
role: 'org:admin', // or 'org:member'
})
```
### Update user metadata
**Always explain the three metadata types before asking which to use:**
| Type | Field | Readable by | Writable by | Use for |
|------|-------|-------------|-------------|---------|
| Public | `public_metadata` | Client + Server | **Server only** | Plan tier, roles, feature flags the frontend reads |
| Private | `private_metadata` | **Server only** | **Server only** | Stripe IDs, compliance flags, internal identifiers |
| Unsafe |Preview of the first 4,000 characters. Read full instructions →
Referenced files: 6 — file references are metadata, not package contents.
clerk-billing20.1 KB
---
name: clerk-billing
description: Clerk Billing for subscription management - render Clerk's PricingTable
and in-app checkout drawer, configure subscription plans, seat-limit plans for
B2B, feature entitlements with has(), and billing webhooks. Use for SaaS
monetization, plan gating, checkout flows, trials, invoicing, and subscription
lifecycle management.
allowed-tools: WebFetch
license: MIT
compatibility: Requires NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY, CLERK_SECRET_KEY, and CLERK_WEBHOOK_SIGNING_SECRET. Billing must be enabled in Clerk Dashboard → Billing. Development instances can use the shared Clerk development gateway; production instances require a Stripe account for payment processing.
metadata:
author: clerk
version: 1.1.0
---
# Billing
> **STOP, prerequisite.** Billing must be enabled before any `<PricingTable />`, `<CheckoutButton />`, `has({ plan })`, or `has({ feature })` usage works. Two paths: (1) [Dashboard → Billing → Settings](https://dashboard.clerk.com/last-active?path=billing/settings), or (2) `clerk enable billing` (see "Agent-first: Programmatic billing config" below). Enabling auto-creates default `free_user` / `free_org` plans. Dev instances can use the shared Clerk development gateway (no Stripe account needed); production requires a Stripe account for payment processing only.
>
> **Note**: Billing APIs are still experimental. Pin your `@clerk/nextjs` and `clerk-js` package versions. See `clerk` skill for the supported version table.
## Quick Start
1. **Enable Billing**, via [Dashboard → Billing → Settings](https://dashboard.clerk.com/last-active?path=billing/settings) or `clerk enable billing` (see Agent-first section). Skipping this throws `cannot_render_billing_disabled` in dev and renders empty in prod.
2. **Create plans in the matching tab**, [Dashboard → Billing → Plans](https://dashboard.clerk.com/last-active?path=billing/plans). Two tabs, slugs scoped per tab, not movable after creation:
- **User Plans** → `<PricingTable />` (default `for="user"`)
- **Organization Plans** → `<PricingTable for="organization" />`
Wrong-tab is the #1 cause of an empty `<PricingTable />`. Plans live in Clerk; not synced to Stripe.
3. **Add features inside a plan**, open the plan in Dashboard → Billing → Plans, use its Features section. Features are scoped per plan, not global. The same slug can attach to multiple plans; `has({ feature: 'export' })` matches if the active plan contains that slug.
4. **Render `<PricingTable />`** (pass `for="organization"` for B2B).
5. **Gate access** with `has({ plan })` or `has({ feature })` from `auth()`.
6. **Handle billing webhooks** for subscription lifecycle.
## Dashboard shortcuts
| Action | URL |
|---|---|
| Enable Billing | `https://dashboard.clerk.com/last-active?path=billing/settings` |
| Create / edit plans | `https://dashboard.clerk.com/last-active?path=billing/plans` |
| Membership mode (B2C + B2B coexistence) | `https://dashboard.clerk.com/last-active?path=organizations-settings` |
| Edit features | Plans → click a plan → Features section (no direct URL) |
## Agent-first: Programmatic billing config
The full billing config (enable toggles, plans, features, plan-feature attachments) is editable via PLAPI without touching the Dashboard. Useful for agents seeding plans, replicating config across instances, or version-controlling billing structure.
Pre-req: project linked to the Clerk app (`clerk auth login` + `clerk link`, see `clerk-setup`). Billing is account-only — unlike orgs, it cannot be enabled on an unclaimed app; claim the app first.
### Enable Billing via CLI
```bash
clerk enable billing # both targets (default, auto-creates free_user + free_org plans)
clerk enable billing --for org # org only
clerk enable billing --for user # user only
```
### Pull current billing config
```bash
clerk config pull --keys billing > billing.json
```
This writes the current billing config (toggles + plans + features) for tPreview of the first 4,000 characters. Read full instructions →
Referenced files: 5 — file references are metadata, not package contents.
clerk-chrome-extension-patterns11.4 KB
---
name: clerk-chrome-extension-patterns
description: 'Chrome Extension auth with @clerk/chrome-extension -- popup/sidepanel
setup, syncHost for OAuth/SAML via web app, createClerkClient for service workers
and headless extensions, stable CRX ID. Triggers on: Chrome extension auth, Plasmo
clerk, popup sign-in, syncHost, background service worker token, createClerkClient,
headless extension.'
license: MIT
allowed-tools: WebFetch
compatibility: Requires PLASMO_PUBLIC_CLERK_PUBLISHABLE_KEY (Plasmo prefix for public env vars) and CLERK_FRONTEND_API.
metadata:
author: clerk
version: 2.0.0
references:
- references/sync-host.md
- references/create-clerk-client.md
- references/content-scripts.md
- references/headless-extension.md
---
# Chrome Extension Patterns
## CRITICAL RULES
1. OAuth (Google, GitHub, etc.) and SAML are NOT supported in popups or side panels -- use `syncHost` to delegate auth to your web app
2. Email links (magic links) don't work in popups -- the popup closes when the user clicks outside, resetting sign-in state
3. Side panels don't auto-refresh auth state -- users must close and reopen the side panel after signing in via the web app
4. Service workers and content scripts have NO access to Clerk React hooks -- use `createClerkClient()` or message passing
5. Extension URLs use `chrome-extension://` not `http://` -- all redirect URLs must use `chrome.runtime.getURL('.')`
6. Without a stable CRX ID, every rebuild breaks auth -- configure `key` in manifest BEFORE deploying
7. Content scripts cannot use Clerk directly due to origin restrictions -- Clerk enforces strict allowed origins
8. Bot protection must be DISABLED in Clerk Dashboard -- Cloudflare bot detection is not supported in extension environments
## Authentication Options
| Method | Popup | Side Panel | syncHost (with web app) |
|--------|-------|------------|------------------------|
| Email + OTP | Yes | Yes | Yes |
| Email + Link | No | No | Yes |
| Email + Password | Yes | Yes | Yes |
| Username + Password | Yes | Yes | Yes |
| SMS + OTP | Yes | Yes | Yes |
| OAuth (Google, GitHub, etc.) | **NO** | **NO** | **YES** |
| SAML | **NO** | **NO** | **YES** |
| Passkeys | Yes | Yes | Yes |
| Google One Tap | No | No | Yes |
| Web3 | No | No | Yes |
## Quick Start (Plasmo)
```bash
npx create-plasmo --with-tailwindcss --with-src my-extension
cd my-extension
npm install @clerk/chrome-extension
```
Enable **Native API** in Clerk Dashboard under Native applications. Required for all extension integrations.
`.env.development`:
```
PLASMO_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_...
CLERK_FRONTEND_API=https://your-app.clerk.accounts.dev
```
`src/popup.tsx`:
```tsx
import { ClerkProvider, Show, SignInButton, SignUpButton, UserButton } from '@clerk/chrome-extension'
const PUBLISHABLE_KEY = process.env.PLASMO_PUBLIC_CLERK_PUBLISHABLE_KEY
const EXTENSION_URL = chrome.runtime.getURL('.')
if (!PUBLISHABLE_KEY) {
throw new Error('Missing PLASMO_PUBLIC_CLERK_PUBLISHABLE_KEY')
}
function IndexPopup() {
return (
<ClerkProvider
publishableKey={PUBLISHABLE_KEY}
afterSignOutUrl={`${EXTENSION_URL}/popup.html`}
signInFallbackRedirectUrl={`${EXTENSION_URL}/popup.html`}
signUpFallbackRedirectUrl={`${EXTENSION_URL}/popup.html`}
>
<Show when="signed-out">
<SignInButton mode="modal" />
<SignUpButton mode="modal" />
</Show>
<Show when="signed-in">
<UserButton />
</Show>
</ClerkProvider>
)
}
export default IndexPopup
```
Use `mode="modal"` for `SignInButton` -- navigating to a separate page breaks the popup flow.
## syncHost -- Sync Auth with Web App
Use this when you need OAuth, SAML, or want the extension to reflect sign-in from your web app.
**How it works**: The extension reads the Clerk session cookie from your web app's domain via `host_permissions`.
**Step 1 -- Environment variables:**
`.env.development`:
```
PLASMO_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_..Preview of the first 4,000 characters. Read full instructions →
Referenced files: 8 — file references are metadata, not package contents.
clerk-cli36.3 KB
--- name: clerk-cli description: >- Operate the Clerk CLI (`clerk` binary) for authentication, user/org/session management, impersonation, local webhook testing, deploy verification, instance config, env keys, feature toggles, and any Clerk Backend, Platform, or Frontend API call. Use when the user mentions Clerk management tasks, "list clerk users", "impersonate a user", "test webhooks locally", "enable orgs", "enable billing", "clerk env pull", "clerk doctor", "clerk deploy", "clerk api", or any ad-hoc Clerk API request. Prefer the CLI over raw HTTP: it handles auth, key resolution, app/instance targeting, and formatting automatically. license: MIT --- # Clerk CLI The `clerk` binary is a pre-authenticated gateway to Clerk's Backend API and Platform API, plus project-level tooling (auth, linking, env pulls, instance config). When the user asks anything that touches a Clerk resource, reach for `clerk` first instead of hand-rolling `curl`. > This skill targets clerk `latest`. If `clerk --version` disagrees with the latest available CLI, refresh it with `clerk update`, or invoke the latest through a package runner such as `bunx clerk@latest`. The binary is always the source of truth, so run `clerk <command> --help` to verify anything this skill claims. ## Execution environment (prefer the host, understand the sandbox warning) Most AI coding agents default to running shell commands in a sandbox where the user's home directory, OS keychain, browser launch, localhost callback binding, or network access may be blocked. The Clerk CLI depends on all of those host capabilities: - **OS credential store**: `clerk auth login` stores the OAuth token in the system keychain. A sandbox without keychain access reports "not logged in" even when the host is authenticated. - **Home-directory Clerk state**: saved config, cached metadata, and fallback credentials live under the user's Clerk config/data directories. - **Linked project metadata**: resolved from the repo's git remote plus Clerk config. Sandboxes with stripped repo state or blocked home-dir reads can misreport "not linked". - **Local `.env*` files**: publishable and secret keys materialized by `clerk env pull`. - **Outbound network access to Clerk**: every Backend and Platform API call. - **Browser + localhost OAuth callback**: `clerk auth login` needs both. In agent mode, the CLI now does a **best-effort warn-once check** at the host-sensitive library boundaries. When it detects that host-only Clerk state or system capabilities are unavailable, it emits: ```text Host-only Clerk state or system capabilities may be unavailable in agent mode. This may be a sandboxed run. Re-run this command on the host shell before trusting auth, link, env, or API failures. ``` Treat that warning as authoritative. The command may continue, but any auth, link, env, config, API, browser, or OAuth callback failure from that invocation is untrusted until you rerun the same command on the host. **Prefer these commands on the user's host shell, not in a sandbox:** `clerk doctor`, `clerk whoami`, `clerk auth login`, `clerk link`, `clerk env pull`, `clerk apps ...`, `clerk config ...`, `clerk api ...`. If a command was accidentally run in a sandbox and it reports `Not logged in`, `auth_required`, `not linked`, missing env, keychain/file permission errors, or network failures, **do not treat the result as authoritative**. Rerun it on the host before acting on it or reporting it to the user. ## Invoking the CLI Before running any `clerk` command, figure out which binary to invoke and bind that choice for the rest of the session: ```sh # 1. Prefer a globally installed binary when it matches the skill's target version. command -v clerk >/dev/null 2>&1 && clerk --version ``` If that prints `latest` or any version you trust, use bare `clerk` for the rest of the session. Otherwise fall back to a package runner, in this order (matches the CLI's own `preferredRunner` logic,
Preview of the first 4,000 characters. Read full instructions →
Referenced files: 3 — file references are metadata, not package contents.
clerk-custom-ui6.34 KB
---
name: clerk-custom-ui
description: Custom authentication flows and component appearance - hooks (useSignIn,
useSignUp), themes, colors, fonts, CSS. Use for custom sign-in/sign-up flows, appearance
styling, visual customization, branding.
allowed-tools: WebFetch
license: MIT
metadata:
author: clerk
version: 2.3.0
---
# Custom UI
> **Prerequisite**: Ensure `ClerkProvider` wraps your app. See `clerk-setup` skill.
>
> **Version**: Check `package.json` for the SDK version — see `clerk` skill for the version table. This determines which custom flow references to use below.
This skill covers two areas:
1. **Custom authentication flows** — build your own sign-in/sign-up UI with hooks
2. **Appearance customization** — theme, style, and brand Clerk's pre-built components
## What Do You Need?
| Task | Reference |
|------|-----------|
| Custom sign-in (Core 2 / LTS) | core-2/custom-sign-in.md |
| Custom sign-up (Core 2 / LTS) | core-2/custom-sign-up.md |
| Custom sign-in (Current SDK v7+) | core-3/custom-sign-in.md |
| Custom sign-up (Current SDK v7+) | core-3/custom-sign-up.md |
| Show component pattern (Current SDK) | core-3/show-component.md |
## Custom Flow References
| Task | Core 2 | Current |
|------|--------|---------|
| Custom sign-in (useSignIn) | `core-2/custom-sign-in.md` | `core-3/custom-sign-in.md` |
| Custom sign-up (useSignUp) | `core-2/custom-sign-up.md` | `core-3/custom-sign-up.md` |
| `<Show>` component | *(use `<SignedIn>`, `<SignedOut>`, `<Protect>`)* | `core-3/show-component.md` |
---
## Appearance Customization
Appearance customization applies to both Core 2 and the current SDK.
### Component Customization Options
| Task | Documentation |
|------|---------------|
| Appearance prop overview | https://clerk.com/docs/nextjs/guides/customizing-clerk/appearance-prop/overview |
| Options (structure, logo, buttons) | https://clerk.com/docs/nextjs/guides/customizing-clerk/appearance-prop/layout |
| Themes (pre-built dark/light) | https://clerk.com/docs/nextjs/guides/customizing-clerk/appearance-prop/themes |
| Variables (colors, fonts, spacing) | https://clerk.com/docs/nextjs/guides/customizing-clerk/appearance-prop/variables |
| CAPTCHA configuration | https://clerk.com/docs/nextjs/guides/customizing-clerk/appearance-prop/captcha |
| Bring your own CSS | https://clerk.com/docs/nextjs/guides/customizing-clerk/appearance-prop/bring-your-own-css |
### Appearance Pattern
```typescript
<SignIn
appearance={{
variables: {
colorPrimary: '#0000ff',
borderRadius: '0.5rem',
},
options: {
logoImageUrl: '/logo.png',
socialButtonsVariant: 'iconButton',
},
}}
/>
```
> **Core 2 ONLY (skip if current SDK):** The `options` property was named `layout`. Use `layout: { logoImageUrl: '...', socialButtonsVariant: '...' }` instead of `options`.
### variables (colors, typography, borders)
| Property | Description |
|----------|-------------|
| `colorPrimary` | Primary color throughout |
| `colorBackground` | Background color |
| `borderRadius` | Border radius (default: `0.375rem`) |
**Opacity change:** `colorRing` and `colorModalBackdrop` now render at full opacity. Use explicit `rgba()` values if you need transparency.
> **Core 2 ONLY (skip if current SDK):** `colorRing` and `colorModalBackdrop` rendered at 15% opacity by default.
### options (structure, logo, social buttons)
| Property | Description |
|----------|-------------|
| `logoImageUrl` | URL to custom logo |
| `socialButtonsVariant` | `'blockButton'` \| `'iconButton'` \| `'auto'` |
| `socialButtonsPlacement` | `'top'` \| `'bottom'` |
| `showOptionalFields` | Show optional fields (default: `false`) |
> **Core 2 ONLY (skip if current SDK):** This property is called `layout`, not `options`. Also, `showOptionalFields` defaulted to `true`.
### Themes
Install themes from `@clerk/ui`:
```bash
npm install @clerk/ui
```
```typescript
import { dark } from '@clerk/ui/themes'
<ClerkProvider appearance={{ theme: dark Preview of the first 4,000 characters. Read full instructions →
Referenced files: 5 — file references are metadata, not package contents.
clerk-expo11 KB
--- name: clerk-expo description: Add Clerk authentication to Expo and React Native apps using @clerk/expo. Use for Expo setup, prebuilt native components (AuthView, UserButton), custom sign-in/sign-up flows (email, password, SMS/phone OTP, MFA), OAuth/SSO, native Google/Apple sign-in, Expo Router protected routes, biometrics, and push notifications. Do not use for native Swift/iOS, native Android/Kotlin, or web-only framework projects. license: MIT allowed-tools: WebFetch metadata: author: clerk version: 2.0.0 compatibility: Requires @clerk/expo v3.4+ (written against v3.6.x, July 2026). Expo SDK 53-56, React Native 0.75+. --- # Clerk Expo (React Native) Implement Clerk in Expo / React Native projects. This skill inlines verified patterns for the stable surface (provider, token cache, flows) and requires source inspection of the installed `@clerk/expo` package for anything volatile (component props, hook signatures). ## Activation Rules Activate when either is true: - The user asks for auth in an Expo or React Native app, or mentions `@clerk/expo`, `ClerkProvider`, Expo Router auth, or Clerk hooks in a native app. - The project is Expo/React Native (`app.json` / `app.config.js`, `expo` in `package.json`, `metro.config.js`, `@clerk/expo` dependency). Route away when: - Native iOS/Swift project (`.xcodeproj`, `Package.swift`) → `clerk-swift` - Native Android/Kotlin project (`build.gradle` without React Native) → `clerk-android` - Web-only framework (Next.js, Remix, plain React, etc.) → the matching framework skill ## Intent Map Match what the user asked for, then load the reference(s) listed. Load only what the task needs. | User intent (examples) | Path | Reference | |------------------------|------|-----------| | "Add auth to my app" / "add sign-in with Clerk" | Prebuilt native components (default) | references/setup.md + references/prebuilt-components.md | | "Add auth" but Expo Go / web / custom UI required | Custom flows | references/setup.md + references/custom-flows.md | | "Add phone / SMS auth", "email OTP", "passwordless" | Custom flow, `phoneCode` / `emailCode` | references/custom-flows.md | | "Sign in with Google/Apple/GitHub", "social login", "SSO" | Browser SSO or native buttons | references/sso-and-native-auth.md | | "MFA / 2FA / TOTP", "forgot password", "email link" | Custom flow additions | references/custom-flows.md | | "Protect routes/screens", "redirect if signed out" | Expo Router guards | references/protected-routes.md | | "Show user profile", "org switching", "push notifications", "sign out", "call my backend" | App recipes | references/recipes.md | | "Biometric login", "Face ID", "passkeys" | Device features | references/recipes.md | ## Default Path Decision When the user says "add auth" without specifying UI: 1. **Default to prebuilt native components** (`AuthView` + `UserButton` from `@clerk/expo/native`). Fastest to working auth; UI is maintained by Clerk. Tell the developer they are in beta and require a development build. 2. **Fall back to custom flows** when any of these hold — say why when you switch: - The project must run in Expo Go (no dev build). - The app targets web (native components don't render on web). - The developer wants their own UI or a specific brand experience beyond theming. 3. If the developer has an existing auth UI, extend what's there — don't rip out custom flows to insert `AuthView` (or vice versa) without being asked. Do not blend prebuilt components and custom flows for the same auth step (e.g. `AuthView` plus a custom password form). Blending is allowed only when the developer explicitly asks. ## Quick Workflow 1. Confirm project type (Expo/RN) and pick the path per the Intent Map / Default Path rules. 2. Follow references/setup.md: install, env key, provider, token cache, config plugin, build type. 3. Verify dashboard prerequisites (Gate 2 and Gate 3 below). 4. Implement from the selected reference only. 5. Verify by building, not just b
Preview of the first 4,000 characters. Read full instructions →
Referenced files: 7 — file references are metadata, not package contents.
clerk-mcp1.13 KB
--- name: clerk-mcp description: Use when implementing Clerk authentication, Clerk SDK usage, Clerk quickstarts, B2B SaaS organization flows, billing examples, or other Clerk integration patterns where the Clerk MCP server can provide snippets or guidance. --- # Clerk MCP Use the bundled `clerk` MCP server when the task involves Clerk implementation guidance, especially: - Adding Clerk authentication to a frontend or backend app. - Choosing or applying Clerk SDK hooks, helpers, or components. - Implementing B2B SaaS organization flows, organization switching, role checks, or billing patterns. - Looking up Clerk quickstarts for Next.js App Router, React/Vite, Expo, Astro, Remix, Express, or Go. Prefer MCP-provided snippets and quickstarts over guessing API shapes from memory. Start with `list_clerk_sdk_snippets` when the right slug is unclear, then call `clerk_sdk_snippet` for the specific snippet or bundle. Current public MCP scope is guidance-only: SDK snippets, snippet bundles, and quickstart resources. Do not assume live Clerk account/user/organization tools are available unless the MCP tool list shows them in the current session.
clerk-nextjs-patterns8.11 KB
---
name: clerk-nextjs-patterns
description: Advanced Next.js patterns - middleware, Server Actions, caching with
Clerk.
license: MIT
allowed-tools: WebFetch
compatibility: Requires NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY and CLERK_SECRET_KEY. For manual JWT verification (standalone API servers without Clerk middleware), additionally requires CLERK_JWT_KEY or CLERK_PEM_PUBLIC_KEY.
metadata:
author: clerk
version: 2.2.0
---
# Next.js Patterns
> **Version**: Check `package.json` for the SDK version — see `clerk` skill for the version table. Core 2 differences are noted inline with `> **Core 2 ONLY (skip if current SDK):**` callouts.
For basic setup, see `clerk-setup` skill.
## What Do You Need?
| Task | Reference |
|------|-----------|
| Server vs client auth (`auth()` vs hooks) | references/server-vs-client.md |
| Configure middleware (public-first vs protected-first) | references/middleware-strategies.md |
| Protect Server Actions | references/server-actions.md |
| API route auth (401 vs 403) | references/api-routes.md |
| Cache auth data (user-scoped caching) | references/caching-auth.md |
## References
| Reference | Description |
|-----------|-------------|
| `references/server-vs-client.md` | `await auth()` vs hooks |
| `references/middleware-strategies.md` | Public-first vs protected-first, `proxy.ts` (Next.js <=15: `middleware.ts`) |
| `references/server-actions.md` | Protect mutations |
| `references/api-routes.md` | 401 vs 403 |
| `references/caching-auth.md` | User-scoped caching |
## Mental Model
Server vs Client = different auth APIs:
- **Server**: `await auth()` from `@clerk/nextjs/server` (async!)
- **Client**: `useAuth()` hook from `@clerk/nextjs` (sync)
Never mix them. Server Components use server imports, Client Components use hooks.
Key properties from `auth()`:
- `isAuthenticated` — boolean, replaces the `!!userId` pattern
- `sessionStatus` — `'active'` | `'pending'`, for detecting incomplete session tasks
- `userId`, `orgId`, `orgSlug`, `has()`, `protect()` — unchanged
> **Core 2 ONLY (skip if current SDK):** `isAuthenticated` and `sessionStatus` are not available. Check `!!userId` instead.
## Minimal Pattern
```typescript
// Server Component
import { auth } from '@clerk/nextjs/server'
export default async function Page() {
const { isAuthenticated, userId } = await auth() // MUST await!
if (!isAuthenticated) return <p>Not signed in</p>
return <p>Hello {userId}</p>
}
```
> **Core 2 ONLY (skip if current SDK):** `isAuthenticated` is not available. Use `if (!userId)` instead.
### Conditional Rendering with `<Show>`
For client-side conditional rendering based on auth state. `<Show>` covers both authentication checks and authorization (feature, plan, role, permission) in one component.
**Authentication check:**
```tsx
import { Show } from '@clerk/nextjs'
<Show when="signed-in" fallback={<p>Please sign in</p>}>
<Dashboard />
</Show>
```
**Authorization checks (B2B):**
```tsx
// Feature-based (preferred — features can move between plans without redeploy)
<Show when={{ feature: 'analytics' }} fallback={<UpgradePrompt />}>
<AnalyticsDashboard />
</Show>
// Permission-based (preferred over role-based for granular access)
<Show when={{ permission: 'org:invoices:create' }}>
<NewInvoiceButton />
</Show>
// Plan-based (tier-level gating)
<Show when={{ plan: 'pro' }}>
<ProFeatures />
</Show>
// Role-based (use sparingly — prefer permission)
<Show when={{ role: 'org:admin' }}>
<AdminPanel />
</Show>
```
**Callback for complex logic:**
```tsx
<Show when={(has) => has({ role: 'org:admin' }) || has({ role: 'org:billing_manager' })}>
<BillingActions />
</Show>
```
> **Core 2 ONLY (skip if current SDK):** `<Show>` does not exist. For authentication, use `<SignedIn>` and `<SignedOut>`. For authorization (role / permission), use `<Protect>` with the same prop names (`role`, `permission`, `condition`). Feature- and plan-based variants require Core 3. See `clerk-custom-ui` skill, `core-Preview of the first 4,000 characters. Read full instructions →
Referenced files: 11 — file references are metadata, not package contents.
clerk-nuxt-patterns3.1 KB
---
name: clerk-nuxt-patterns
description: 'Nuxt 3 auth patterns with @clerk/nuxt - middleware, composables, server
API routes, SSR. Triggers on: Nuxt auth, useAuth composable, clerkMiddleware Nuxt,
server API Clerk, Nuxt route protection.'
license: MIT
allowed-tools: WebFetch
metadata:
author: clerk
version: 1.0.0
---
# Nuxt Patterns
## What Do You Need?
| Task | Reference |
|------|-----------|
| Protect routes with middleware | references/nuxt-middleware.md |
| Auth in server API routes (Nitro) | references/server-api-routes.md |
| useAuth / useUser in components | references/composables.md |
| SSR-safe auth patterns | references/ssr-auth.md |
## References
| Reference | Description |
|-----------|-------------|
| `references/nuxt-middleware.md` | Route protection, clerkMiddleware() |
| `references/server-api-routes.md` | Nitro server route auth |
| `references/composables.md` | useAuth, useUser, useClerk |
| `references/ssr-auth.md` | SSR hydration, server vs client |
## Setup
```
npm install @clerk/nuxt
```
`.env`:
```
NUXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_...
NUXT_CLERK_SECRET_KEY=sk_...
```
`nuxt.config.ts`:
```typescript
export default defineNuxtConfig({
modules: ['@clerk/nuxt'],
})
```
This single line auto-configures middleware, plugins, and component auto-imports.
## Mental Model
`@clerk/nuxt` auto-imports all Clerk components and composables — no explicit imports needed in `<script setup>`.
- **Composables** (`useAuth`, `useUser`) — client-side reactive, inside `<script setup>`
- **Server routes** (`clerkClient`) — Nitro server routes, `event.context.auth`
- **Middleware** (`clerkMiddleware`) — auto-registered, use `auth().protect()` to lock routes
## Minimal Pattern
```vue
<!-- pages/dashboard.vue -->
<script setup lang="ts">
definePageMeta({ middleware: 'auth' })
const { userId } = useAuth()
</script>
<template>
<Show when="signed-in">
<p>Hello {{ userId }}</p>
</Show>
</template>
```
> `definePageMeta({ middleware: 'auth' })` uses the built-in auth middleware from `@clerk/nuxt`.
## Common Pitfalls
| Symptom | Cause | Fix |
|---------|-------|-----|
| Composables return `undefined` on server | useAuth is client-only | Use `event.context.auth` in server routes |
| Route not protected | Missing `middleware: 'auth'` meta | Add `definePageMeta({ middleware: 'auth' })` |
| `clerkClient` not available | Wrong import path | Import from `@clerk/nuxt/server` |
| Hydration mismatch | Rendering auth state before mounted | Wrap in `<ClientOnly>` or check `isLoaded` |
| Env vars not picked up | Wrong prefix | Nuxt requires `NUXT_PUBLIC_` for public, `NUXT_` for server |
## Org-Aware Pattern
```vue
<script setup lang="ts">
const { orgId, orgRole } = useAuth()
</script>
<template>
<div v-if="orgId">
<p>Org: {{ orgId }}</p>
<p v-if="orgRole === 'org:admin'">Admin panel</p>
</div>
<div v-else>
<OrganizationSwitcher />
</div>
</template>
```
## See Also
- `clerk-setup` - Initial Clerk install
- `clerk-custom-ui` - Custom flows & appearance
- `clerk-orgs` - B2B organizations
## Docs
[Nuxt SDK](https://clerk.com/docs/nuxt/getting-started/quickstart)
Referenced files: 8 — file references are metadata, not package contents.
clerk-orgs18.9 KB
---
name: clerk-orgs
description: Clerk Organizations for B2B SaaS - create multi-tenant apps with org
switching, role-based access, verified domains, and enterprise SSO. Use for team
workspaces, RBAC, org-based routing, member management.
allowed-tools: WebFetch
license: MIT
compatibility: Requires NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY and CLERK_SECRET_KEY. Organizations must be enabled in Clerk Dashboard → Organizations. Membership mode (required vs optional) must match the B2B vs B2C + B2B coexistence story of your app.
metadata:
author: clerk
version: 3.1.0
---
# Organizations (B2B SaaS)
> **STOP — prerequisite.** Organizations must be enabled before any org-related API, hook, or component works. Two paths: (1) [Dashboard → Organizations settings](https://dashboard.clerk.com/last-active?path=organizations-settings), or (2) `clerk enable orgs` (see "Agent-first: Programmatic org management" below). Pick the Membership mode deliberately: `Membership required` (default since 2025-08-22) routes signed-in users through the `choose-organization` task and disables personal accounts, while `Membership optional` keeps personal accounts available for B2C + B2B coexistence. Pick `optional` if you need personal subscriptions alongside org subscriptions.
>
> **Version**: This skill targets current SDKs (`@clerk/nextjs` v7+, `@clerk/react` v6+ — Core 3). Core 2 differences are noted inline with `> **Core 2 ONLY (skip if current SDK):**` callouts — see `clerk` skill for the full version table.
## Quick Start
1. **Enable Organizations** — via [Dashboard → Organizations settings](https://dashboard.clerk.com/last-active?path=organizations-settings) or `clerk enable orgs` (see Agent-first section). Pick `Membership required` (B2B-only) or `Membership optional` (B2C + B2B).
2. **Create an org** — via `<OrganizationSwitcher />`, `<CreateOrganization />`, or programmatically with `clerkClient().organizations.createOrganization()`.
3. **Protect routes** — read `orgId` / `orgSlug` from `auth()` and gate with `has({ role })` or `has({ permission })`.
4. **Manage members** — send invitations via Backend API or the built-in `<OrganizationProfile />` tab.
5. **Cap membership** — set `maxAllowedMemberships` at org creation or pick a seat-limited Billing Plan (see `clerk-billing` skill).
## What Do You Need?
| Task | Reference |
|------|-----------|
| System permissions catalog, custom roles, role sets | references/roles-permissions.md |
| Invitation lifecycle (create, list, revoke, built-in UI) | references/invitations.md |
| Enterprise SSO setup, provider field access, domain verification | references/enterprise-sso.md |
| Next.js adaptations for orgs (role/permission middleware, slug invariants, orgId-scoped writes) | references/nextjs-patterns.md |
## References
| Reference | Description |
|-----------|-------------|
| `references/roles-permissions.md` | Default + custom roles, System Permissions catalog, permission naming |
| `references/invitations.md` | Backend API for invitations + built-in UI |
| `references/enterprise-sso.md` | SAML/OIDC per-org, domain verification, correct field access |
| `references/nextjs-patterns.md` | Next.js adaptations specific to orgs. For generic Next.js patterns see `clerk-nextjs-patterns` skill. |
## Dashboard shortcuts
| Action | URL |
|---|---|
| Enable Organizations + Membership mode | `https://dashboard.clerk.com/last-active?path=organizations-settings` |
| Manage roles + permissions | `https://dashboard.clerk.com/last-active?path=organizations-settings/roles` |
| Create/edit an organization | `https://dashboard.clerk.com/last-active?path=organizations` |
| Webhooks for org events | `https://dashboard.clerk.com/last-active?path=webhooks` |
## Agent-first: Programmatic org management
Org settings (enable toggle, membership cap, admin delete, domains) are patchable via PLAPI Instance Config. Org CRUD + memberships + invitations live in BAPI. Useful for agents seeding orgs, replicating settings aPreview of the first 4,000 characters. Read full instructions →
Referenced files: 5 — file references are metadata, not package contents.
clerk-react-patterns4.06 KB
---
name: clerk-react-patterns
description: 'React SPA auth patterns with @clerk/react for Vite/CRA - ClerkProvider
setup, useAuth/useUser/useClerk hooks, React Router protected routes, custom sign-in
flows. Triggers on: Vite Clerk setup, React Router auth, useAuth hook, protected
route, custom sign-in form React.'
license: MIT
allowed-tools: WebFetch
metadata:
author: clerk
version: 1.0.0
---
# React SPA Patterns
> This skill covers `@clerk/react` for Vite/CRA SPAs. For Next.js use `clerk-nextjs-patterns`. For TanStack Start use `clerk-tanstack-patterns`.
## What Do You Need?
| Task | Reference |
|------|-----------|
| useAuth / useUser / useClerk hooks | references/hooks.md |
| Protected routes with React Router | references/protected-routes.md |
| Custom sign-in / sign-up forms | references/custom-flows.md |
| React Router v6/v7 integration | references/router-integration.md |
## References
| Reference | Description |
|-----------|-------------|
| `references/hooks.md` | useAuth, isLoaded guard |
| `references/protected-routes.md` | ProtectedRoute pattern |
| `references/custom-flows.md` | useSignIn, useSignUp flows |
| `references/router-integration.md` | React Router v6/v7 setup |
## Setup
```
npm install @clerk/react
```
`.env`:
```
VITE_CLERK_PUBLISHABLE_KEY=pk_...
```
`src/main.tsx`:
```tsx
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import { ClerkProvider } from '@clerk/react'
import App from './App.tsx'
const PUBLISHABLE_KEY = import.meta.env.VITE_CLERK_PUBLISHABLE_KEY
createRoot(document.getElementById('root')!).render(
<StrictMode>
<ClerkProvider publishableKey={PUBLISHABLE_KEY}>
<App />
</ClerkProvider>
</StrictMode>,
)
```
## Mental Model
`@clerk/react` is client-only — there is no server-side `auth()`. All auth state comes from hooks.
- `isLoaded` must be `true` before trusting `isSignedIn` — always guard on `isLoaded`
- `useClerk()` gives access to `signOut`, `openSignIn`, `openUserProfile` and other methods
- `getToken()` from `useAuth()` fetches the session JWT for API calls
## Minimal Pattern
```tsx
import { useAuth } from '@clerk/react'
export function Dashboard() {
const { isLoaded, isSignedIn, userId } = useAuth()
if (!isLoaded) return <div>Loading...</div>
if (!isSignedIn) return <div>Please sign in</div>
return <div>Hello {userId}</div>
}
```
## Protected Route (React Router v6/v7)
```tsx
import { Navigate, Outlet } from 'react-router-dom'
import { useAuth } from '@clerk/react'
export function ProtectedRoute() {
const { isLoaded, isSignedIn } = useAuth()
if (!isLoaded) return <div>Loading...</div>
if (!isSignedIn) return <Navigate to="/sign-in" replace />
return <Outlet />
}
```
```tsx
<Routes>
<Route element={<ProtectedRoute />}>
<Route path="/dashboard" element={<Dashboard />} />
<Route path="/settings" element={<Settings />} />
</Route>
<Route path="/sign-in" element={<SignIn />} />
</Routes>
```
## Token for API Calls
```tsx
import { useAuth } from '@clerk/react'
export function DataFetcher() {
const { getToken } = useAuth()
async function fetchData() {
const token = await getToken()
if (!token) return
const res = await fetch('/api/data', {
headers: { Authorization: `Bearer ${token}` },
})
return res.json()
}
return <button onClick={fetchData}>Load</button>
}
```
## Common Pitfalls
| Symptom | Cause | Fix |
|---------|-------|-----|
| `isSignedIn` is `undefined` | `isLoaded` is still `false` | Always check `isLoaded` first |
| `ClerkProvider` missing | Provider not at root | Wrap `<App>` in `main.tsx` |
| Env var undefined | Wrong Vite prefix | Use `VITE_CLERK_PUBLISHABLE_KEY`, access via `import.meta.env` |
| Token is `null` | User not signed in | Null-check `getToken()` result |
| Sign-in component shows blank | No `publishableKey` on provider | Pass `publishableKey` explicitly |
## See Also
- `clerk-setup` - Initial Clerk install
- `cPreview of the first 4,000 characters. Read full instructions →
Referenced files: 11 — file references are metadata, not package contents.
clerk-react-router-patterns7.22 KB
---
name: clerk-react-router-patterns
description: 'React Router v7/v8 patterns with Clerk — rootAuthLoader, getAuth in loaders,
clerkMiddleware, protected routes, SSR user data, org switching. Triggers on: react-router
auth, rootAuthLoader, getAuth loader, react-router protected route, loader authentication,
SSR auth react-router, useNavigate may be used only in the context of a Router.'
license: MIT
allowed-tools: WebFetch
metadata:
author: clerk
version: 1.1.0
---
# React Router Patterns
SDK: `@clerk/react-router` v3.5+. Supports React Router v7.9+ and v8.
## What Do You Need?
| Task | Reference |
|------|-----------|
| Auth in loaders and actions | references/loaders-actions.md |
| Protected routes and redirects | references/protected-routes.md |
| SSR user data and session | references/ssr-auth.md |
## React Router v7 vs v8
Check the installed `react-router` major version before scaffolding — the config differs:
| | v7.9+ | v8+ |
|--|--|--|
| Middleware API | Opt-in: set `future: { v8_middleware: true }` in `react-router.config.ts` | Always on — do NOT set the flag (v8 removed it) |
| `ssr.noExternal` workaround (below) | Not needed | **Required** |
## Minimal Setup
### 1. vite.config.ts (v8 only — REQUIRED)
React Router v8 ships development/production conditional exports. In `react-router dev`,
Vite externalizes `@clerk/react-router` for SSR, so Node resolves the production build of
react-router while the app code gets the development build — two module instances, two
Router contexts. Every request then fails during SSR with:
```
Error: useNavigate() may be used only in the context of a <Router> component.
```
**`npm ls react-router` shows a single copy — that does NOT rule this out.** The
duplication is per export condition, not per installed copy. Do not chase duplicate
installs; add the workaround (upstream issue:
https://github.com/remix-run/react-router/issues/15232):
```ts
import { reactRouter } from '@react-router/dev/vite'
import { defineConfig } from 'vite'
export default defineConfig({
plugins: [reactRouter()],
ssr: {
noExternal: ['@clerk/react-router'],
},
})
```
### 2. root.tsx
```tsx
import { Outlet } from 'react-router'
import { rootAuthLoader, clerkMiddleware } from '@clerk/react-router/server'
import { ClerkProvider } from '@clerk/react-router'
import type { Route } from './+types/root'
export const middleware: Route.MiddlewareFunction[] = [clerkMiddleware()]
export async function loader(args: Route.LoaderArgs) {
return rootAuthLoader(args)
}
export default function App({ loaderData }: Route.ComponentProps) {
return (
<ClerkProvider loaderData={loaderData}>
<Outlet />
</ClerkProvider>
)
}
```
There is no `ClerkApp` HOC in `@clerk/react-router` (that was the `@clerk/remix` API).
Render `<ClerkProvider loaderData={loaderData}>` inside the default export and pass it
the root route's `loaderData`.
### 3. react-router.config.ts (v7 only)
```ts
import type { Config } from '@react-router/dev/config'
export default {
future: {
v8_middleware: true,
},
} satisfies Config
```
On v8, omit the `future` block entirely — the flag no longer exists.
> **Required**: `rootAuthLoader` must be called in `root.tsx`'s loader. Without it, `getAuth` throws in nested loaders.
## Mental Model
React Router v7/v8 uses a middleware + loader pipeline. Clerk plugs into both layers:
- **Middleware** (`clerkMiddleware()`) — runs on every request, attaches auth to context
- **`rootAuthLoader`** — required in `root.tsx` to pass Clerk state to the client
- **`getAuth(args)`** — called inside any loader/action to get the current user
```
Request → clerkMiddleware() → rootAuthLoader → page loader → component
↓ ↓ ↓
attaches auth injects state getAuth(args)
to context to response reads context
```
## Auth in Loaders
```tsx
import { getAuth } from '@clerk/react-router/server'
Preview of the first 4,000 characters. Read full instructions →
Referenced files: 11 — file references are metadata, not package contents.
clerk-setup13.5 KB
---
name: clerk-setup
description: Add Clerk authentication to any project by following the official quickstart
guides.
license: MIT
allowed-tools: WebFetch
compatibility: Requires NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY and CLERK_SECRET_KEY (or framework-specific equivalents like VITE_CLERK_PUBLISHABLE_KEY for Vite-based apps). Keys can be auto-generated by `clerk init` (temporary development keys, no Clerk account required), or pulled from the Clerk Dashboard. Requires Node.js 20.9.0 or higher.
metadata:
author: clerk
version: 2.5.0
---
# Adding Clerk
> **Version**: Check `package.json` for the SDK version — see `clerk` skill for the version table. Core 2 differences are noted inline with `> **Core 2 ONLY (skip if current SDK):**` callouts.
This skill sets up Clerk for authentication by following the official quickstart documentation. For agents, the `clerk` CLI handles most of this end to end — see the next section.
## Agent-first: Provision via CLI
The `clerk` CLI replaces most Dashboard clicks. Three scenarios cover almost everything:
### Scenario A — New project, new Clerk app
```bash
clerk init --framework <next|react|vue|nuxt|astro|react-router|tanstack-react-start|expressjs|fastify|expo> -y
```
`clerk init` installs the SDK, wires the project up, and writes the framework-specific publishable + secret keys to the right env file (e.g. `.env.local` for Next.js, `.env` for Vite-based projects).
**No login required.** Unauthenticated, `clerk init` writes temporary development keys to the project's env file — no account, no browser, no flag. Don't run `clerk auth login` first. Authenticated (or with `--app` / `--login`) it creates and links a real app via PLAPI instead.
`--template <b2b-saas|b2c-saas|native|waitlist>` pre-configures the temporary app. Caveats — a signed-out human in an *existing* project still gets the login flow unless they pass `--keyless`; `--template`/`--fresh` error on any run that targets a real app; login only auto-claims what `clerk init` created. See [clerk-cli](../clerk-cli/references/auth.md#accountless-operating-without-an-account).
### Scenario B — Existing project, existing Clerk app
```bash
clerk auth login # one-time OAuth (skip if already logged in)
clerk link # autolinks if a CLERK_PUBLISHABLE_KEY is in your .env
clerk link --app app_xxx # explicit form, required in agent mode
clerk env pull # writes the framework-detected env vars
```
### Scenario C — Existing project, new Clerk app
```bash
clerk auth login
clerk apps create "My App" --json # returns the new app_id
clerk link --app app_xxx
clerk env pull
```
### Daily ops
```bash
clerk env pull # refresh keys (uses linked profile)
clerk env pull --instance prod # production keys
clerk doctor --json # framework integration health check
```
### Rotate the secret key (replaces Dashboard rotation)
PLAPI exposes secret-key rotation directly. Use raw `clerk api` until the friendly wrapper ships:
```bash
clerk api --platform POST /v1/platform/applications/<app_id>/rotate_secret_keys \
-d '{"delay_old_secrets_expiration_hours": 24, "reason": "scheduled rotation"}'
```
`delay_old_secrets_expiration_hours` keeps the old key valid for the grace period so deploys can roll forward without downtime.
### Notes for agents
- Unclaimed apps created by `clerk init` are configurable without an account — see the [no-account command table](../clerk-cli/references/auth.md#accountless-operating-without-an-account) for which commands work and which need a claimed app.
- `clerk link` (no flags) only autolinks when a `CLERK_PUBLISHABLE_KEY` is already in `.env` / `.env.local`. Without it, agent mode errors out: "Cannot select an application in agent mode." When that happens, run `clerk apps list --json`, and ask the user which `app_id` to link rather than guessing.
- Pass `--json` on `apps list/create`, `usePreview of the first 4,000 characters. Read full instructions →
Referenced files: 1 — file references are metadata, not package contents.
clerk-swift11.8 KB
---
name: clerk-swift
description: Implement Clerk authentication for native Swift and iOS apps using ClerkKit
and ClerkKitUI source-guided patterns. Use for prebuilt AuthView or custom native
flows. Do not use for Expo or React Native projects.
license: MIT
allowed-tools: WebFetch
metadata:
author: clerk
version: 1.2.0
compatibility: Requires Xcode and ClerkKit Swift package
---
# Clerk Swift (Native iOS)
This skill implements Clerk in native Swift/iOS projects by reading installed package source and mirroring current ClerkKit/ClerkKitUI behavior.
## Activation Rules
Activate this skill when either condition is true:
- The user explicitly asks for Swift, SwiftUI, UIKit, or native iOS Clerk implementation.
- The project appears to be native iOS/Swift (for example `.xcodeproj`, `.xcworkspace`, `Package.swift`, Swift targets).
Do not activate this skill when either condition is true:
- The project is Expo.
- The project is React Native.
If Expo/React Native signals are present, route to the general setup skill instead of this one.
## What Do You Need?
| Task | Reference |
|------|-----------|
| Prebuilt AuthView / UserButton (fastest) | references/prebuilt.md |
| Custom API-driven auth flows (full control) | references/custom.md |
## Quick Start
| Step | Action |
|------|--------|
| 1 | Confirm project type is native Swift/iOS and not Expo/React Native |
| 2 | Determine flow type (`prebuilt` or `custom`) and load the matching reference file |
| 3 | Ensure a valid publishable key exists (or ask developer) and wire it directly in configuration |
| 4 | Ensure `clerk-ios` package is installed with correct products for selected flow; if missing, install latest available release using an up-to-next-major version requirement |
| 5 | Inspect installed `ClerkKitUI` source to identify which `Environment` fields drive feature/step gating |
| 6 | Call `/v1/environment` after step 5 and evaluate only against the `ClerkKitUI`-aligned field map |
| 7 | Find the iOS quickstart URL in the installed `clerk-ios` package README, append `.md`, then visit and read the markdown URL to compile a required-step checklist |
| 8 | Verify and complete all quickstart prerequisites for this project (for example associated domains and required capabilities) |
| 9 | Implement flow by following only the selected reference checklist |
## Decision Tree
```text
User asks for Clerk in Swift/iOS
|
+-- Expo/React Native project detected?
| |
| +-- YES -> Do not use this skill
| |
| +-- NO -> Continue
|
+-- Existing auth UI detected?
| |
| +-- Prebuilt views detected -> Load references/prebuilt.md
| |
| +-- Custom flow detected -> Load references/custom.md
| |
| +-- New implementation -> Ask developer prebuilt/custom, then load matching reference
|
+-- Ensure publishable key and direct wiring
|
+-- Ensure clerk-ios is installed
|
+-- Inspect ClerkKitUI Environment field usage
|
+-- Call /v1/environment using that field map
|
+-- Visit/read quickstart URL from installed clerk-ios package README
|
+-- Verify all quickstart prerequisites are completed
|
+-- Implement using selected flow reference
```
## Flow References
After flow type is known, load exactly one:
- Prebuilt flow: [references/prebuilt.md](references/prebuilt.md)
- Custom flow: [references/custom.md](references/custom.md)
Do not blend the two references in a single implementation unless the developer explicitly asks for a hybrid approach.
## Interaction Contract
Before any implementation edits, the agent must have both:
- flow choice: `prebuilt` or `custom`
- a real Clerk publishable key
If either value is missing from the user request/context:
- ask the user for the missing value(s)
- pause and wait for the answer
- do not edit files or install dependencies yet
Only skip asking when the user has already explicitly provided the valuPreview of the first 4,000 characters. Read full instructions →
Referenced files: 2 — file references are metadata, not package contents.
clerk-tanstack-patterns3.42 KB
---
name: clerk-tanstack-patterns
description: 'TanStack React Start auth patterns with @clerk/tanstack-react-start
- createServerFn, beforeLoad guards, loaders, Vinxi server. Triggers on: TanStack
auth, createServerFn clerk, beforeLoad protection, TanStack Start middleware.'
license: MIT
allowed-tools: WebFetch
metadata:
author: clerk
version: 1.0.0
---
# TanStack React Start Patterns
## What Do You Need?
| Task | Reference |
|------|-----------|
| Protect routes with beforeLoad | references/router-guards.md |
| Auth in createServerFn | references/server-functions.md |
| Pass auth to loaders | references/loaders.md |
| Configure Vinxi + clerkMiddleware | references/vinxi-server.md |
## References
| Reference | Description |
|-----------|-------------|
| `references/router-guards.md` | beforeLoad auth redirect |
| `references/server-functions.md` | createServerFn with auth() |
| `references/loaders.md` | Auth context in loaders |
| `references/vinxi-server.md` | clerkMiddleware() setup |
## Setup
```
npm install @clerk/tanstack-react-start
```
`.env`:
```
CLERK_PUBLISHABLE_KEY=pk_...
CLERK_SECRET_KEY=sk_...
```
`src/start.ts` (Vinxi entry):
```typescript
import { clerkMiddleware } from '@clerk/tanstack-react-start/server'
import { createStart } from '@tanstack/react-start'
export const startInstance = createStart(() => {
return {
requestMiddleware: [clerkMiddleware()],
}
})
```
`src/routes/__root.tsx` — wrap with `<ClerkProvider>`:
```tsx
import { ClerkProvider } from '@clerk/tanstack-react-start'
function RootDocument({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
<ClerkProvider>
{children}
</ClerkProvider>
</body>
</html>
)
}
```
## Mental Model
TanStack Start runs on Vinxi. Auth flows through two layers:
1. **Server layer** — `createServerFn` + `auth()` from `@clerk/tanstack-react-start/server`
2. **Router layer** — `beforeLoad` on route definitions, throws `redirect` for unauthenticated
Both layers are server-executed. Client hooks (`useAuth`, `useUser`) are React hooks for the browser side.
## Minimal Pattern
```typescript
import { createFileRoute, redirect } from '@tanstack/react-router'
import { createServerFn } from '@tanstack/react-start'
import { auth } from '@clerk/tanstack-react-start/server'
const authStateFn = createServerFn().handler(async () => {
const { isAuthenticated, userId } = await auth()
if (!isAuthenticated) {
throw redirect({ to: '/sign-in' })
}
return { userId }
})
export const Route = createFileRoute('/dashboard')({
beforeLoad: async () => await authStateFn(),
})
```
## Common Pitfalls
| Symptom | Cause | Fix |
|---------|-------|-----|
| `auth()` returns empty | Missing `clerkMiddleware` in start.ts | Add to `requestMiddleware` array |
| `redirect` not thrown | Using `return` instead of `throw` | `throw redirect(...)` in TanStack |
| Wrong import for `auth` | Mixing client/server imports | Server: `@clerk/tanstack-react-start/server` |
| Loader context missing userId | Not passing from beforeLoad | Return from beforeLoad, access via `context` |
| `ClerkProvider` missing | Forgot root wrapping | Add to `__root.tsx` shell component |
## See Also
- `clerk-setup` - Initial Clerk install
- `clerk-custom-ui` - Custom flows & appearance
- `clerk-orgs` - B2B organizations
## Docs
[TanStack React Start SDK](https://clerk.com/docs/tanstack-react-start/getting-started/quickstart)
Referenced files: 12 — file references are metadata, not package contents.
clerk-testing1.89 KB
---
name: clerk-testing
description: E2E testing for Clerk apps. Use with Playwright or Cypress for auth flow
tests.
allowed-tools: WebFetch
license: MIT
metadata:
author: clerk
version: 1.2.0
compatibility: Requires CLERK_TESTING_TOKEN from Clerk dashboard
---
# Testing
## Decision Tree
| Framework | Documentation |
|-----------|---------------|
| Overview | https://clerk.com/docs/guides/development/testing/overview |
| Playwright | https://clerk.com/docs/guides/development/testing/playwright/overview |
| Cypress | https://clerk.com/docs/guides/development/testing/cypress/overview |
## Mental Model
Test auth = isolated session state. Each test needs fresh auth context.
- `clerkSetup()` initializes test environment
- `setupClerkTestingToken()` bypasses bot detection
- `storageState` persists auth between tests for speed
## Workflow
1. Identify test framework (Playwright or Cypress)
2. WebFetch the appropriate URL from decision tree above
3. Follow official setup instructions
4. Use `pk_test_*` and `sk_test_*` keys only
## Best Practices
- Use `setupClerkTestingToken()` before navigating to auth pages
- Use test API keys: `pk_test_xxx`, `sk_test_xxx`
- Save auth state with `storageState` for faster tests
- Use `page.waitForSelector('[data-clerk-component]')` for Clerk UI
## Anti-Patterns
| Pattern | Problem | Fix |
|---------|---------|-----|
| Production keys in tests | Security risk | Use `pk_test_*` keys |
| No `setupClerkTestingToken()` | Auth fails | Call before navigation |
| UI-based sign-in every test | Slow tests | Use `storageState` |
## Framework-Specific
**Playwright**: Use `globalSetup` for auth state
**Cypress**: Add `addClerkCommands({ Cypress, cy })` to support file
## See Also
- `clerk-setup` - Install Clerk before adding tests
- `clerk-nextjs-patterns` - Next.js patterns being tested
- [Demo Repo](https://github.com/clerk/clerk-playwright-nextjs/tree/main/e2e)
clerk-vue-patterns2.77 KB
---
name: clerk-vue-patterns
description: 'Vue 3 patterns with Clerk — composables (useAuth, useUser,
useClerk, useOrganization), Vue Router guards, Pinia auth store
integration. Triggers on: vue clerk, useAuth vue, clerk composables,
vue router clerk guard, pinia auth clerk. For Nuxt, use clerk-nuxt-patterns instead.'
license: MIT
allowed-tools: WebFetch
metadata:
author: clerk
version: 1.0.0
---
# Vue Patterns
SDK: `@clerk/vue` v2+ (Vue 3). For Nuxt, use `clerk-nuxt-patterns`.
## What Do You Need?
| Task | Reference |
|------|-----------|
| Composables: useAuth, useUser, useOrganization | references/composables.md |
| Vue Router navigation guards | references/vue-router-guards.md |
| Pinia store with auth state | references/pinia-integration.md |
## Mental Model
Vue uses composables from `@clerk/vue`:
- **`useAuth()`** — reactive `isSignedIn`, `userId`, `signOut`
- **`useUser()`** — reactive `user` object
- **`useClerk()`** — full Clerk instance for advanced operations
- **`useOrganization()`** — reactive `organization`, `membership`
## Setup
### Vue (Plain)
```ts
// main.ts
import { clerkPlugin } from '@clerk/vue'
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
app.use(clerkPlugin, {
publishableKey: import.meta.env.VITE_CLERK_PUBLISHABLE_KEY,
})
app.mount('#app')
```
## Composables Usage
```vue
<script setup lang="ts">
import { useAuth, useUser } from '@clerk/vue'
const { isSignedIn, userId, signOut } = useAuth()
const { user } = useUser()
</script>
<template>
<div v-if="isSignedIn">
<p>Hello {{ user?.firstName }}</p>
<button @click="signOut()">Sign Out</button>
</div>
<SignInButton v-else />
</template>
```
## Org Switching
```vue
<script setup lang="ts">
import { useOrganizationList } from '@clerk/vue'
const { userMemberships, setActive } = useOrganizationList()
</script>
<template>
<button
v-for="mem in userMemberships.data ?? []"
:key="mem.organization.id"
@click="setActive({ organization: mem.organization.id })"
>
{{ mem.organization.name }}
</button>
</template>
```
## Common Pitfalls
| Symptom | Cause | Fix |
|---------|-------|-----|
| Composables return `undefined` | Not inside `ClerkProvider` tree | Ensure `app.use(clerkPlugin, { publishableKey })` is called |
| `userId` reactive but not updating | Destructuring loses reactivity | Use `const { userId } = useAuth()` (toRefs-style composable, reactive) |
## Import Map
| What | Import |
|------|--------|
| Composables | `@clerk/vue` |
| Plugin setup | `@clerk/vue` |
| Components | `@clerk/vue` |
## See Also
- `clerk-setup` - Initial Clerk install
- `clerk-custom-ui` - Custom flows & appearance
- `clerk-orgs` - B2B organizations
## Docs
- [Vue SDK](https://clerk.com/docs/vue/getting-started/quickstart)
Referenced files: 10 — file references are metadata, not package contents.
clerk-webhooks13.2 KB
---
name: clerk-webhooks
description: Clerk webhooks for real-time events and data syncing. Verify with verifyWebhook
from the framework-specific package. Handle user, session, organization, billing, and
payment events. Build event-driven features like database sync, notifications, and
integrations.
allowed-tools: WebFetch
license: MIT
metadata:
author: clerk
version: 1.2.0
compatibility: Requires CLERK_WEBHOOK_SIGNING_SECRET (svix signing secret from Clerk dashboard)
---
# Webhooks
Output complete, working webhook handlers with `verifyWebhook(req)` verification in every handler.
## When to Use Webhooks
Webhooks are **asynchronous and eventually consistent**. Delivery is fast but not guaranteed to be immediate, and may occasionally fail (Svix retries on a fixed schedule). Use them for:
- Database sync (a separate users / orgs table that follows Clerk)
- Notifications (welcome emails, Slack pings, internal alerts)
- Integrations triggered by lifecycle events
Do NOT rely on webhook delivery as part of a synchronous flow such as onboarding ("user signs up, then we read X from our DB"). For data the user just created, read it from the [Clerk session token](https://clerk.com/docs/guides/sessions/session-tokens) or call the Backend API directly. Webhooks fill the gap when you need data about *other* users or events the session token doesn't carry.
## Verify Every Webhook
Use `verifyWebhook(req)` from the framework-specific package (`@clerk/nextjs/webhooks`, `@clerk/express/webhooks`, etc.). It reads `CLERK_WEBHOOK_SIGNING_SECRET` automatically and throws on bad signatures. Skipping verification, even for notification-only handlers, exposes the endpoint to spoofed events.
## Make the Webhook Route Public
Webhook routes must be excluded from Clerk middleware protection. Without this, Clerk returns 401.
```typescript
// proxy.ts (Next.js <=15: middleware.ts)
import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server'
const isPublicRoute = createRouteMatcher(['/api/webhooks(.*)'])
export default clerkMiddleware(async (auth, req) => {
if (!isPublicRoute(req)) await auth.protect()
})
```
## Complete Webhook Handler (Next.js App Router)
```typescript
// app/api/webhooks/route.ts
import { verifyWebhook } from '@clerk/nextjs/webhooks'
import { NextRequest } from 'next/server'
import { db } from '@/lib/db'
export async function POST(req: NextRequest) {
// ALWAYS verify - never skip, even for notification-only handlers
let evt
try {
evt = await verifyWebhook(req) // uses CLERK_WEBHOOK_SIGNING_SECRET automatically
} catch (err) {
console.error('Webhook verification failed:', err)
return new Response('Verification failed', { status: 400 })
}
if (evt.type === 'user.created') {
const { id, email_addresses, first_name, last_name } = evt.data
const email = email_addresses[0]?.email_address
const name = `${first_name ?? ''} ${last_name ?? ''}`.trim()
await db.users.create({ data: { clerkId: id, email, name } })
}
if (evt.type === 'user.updated') {
const { id, email_addresses, first_name, last_name } = evt.data
const email = email_addresses[0]?.email_address
await db.users.update({ where: { clerkId: id }, data: { email, first_name, last_name } })
}
if (evt.type === 'user.deleted') {
const { id } = evt.data
await db.users.delete({ where: { clerkId: id } })
}
if (evt.type === 'organizationMembership.created') {
const { organization, public_user_data, role } = evt.data
const orgId = organization.id
const userId = public_user_data.user_id
await db.teamMembers.create({ data: { orgId, userId, role } })
}
if (evt.type === 'organizationMembership.deleted') {
const { organization, public_user_data } = evt.data
const orgId = organization.id
const userId = public_user_data.user_id
await db.teamMembers.delete({ where: { orgId_userId: { orgId, userId } } })
}
return new Response('OK', { status: 200 })
}
``Preview of the first 4,000 characters. Read full instructions →
Referenced files: 2 — file references are metadata, not package contents.
Package details
Publisher declarations from the archived package. These are separate from our research and the live service's terms.
- Package author
- clerk.dev
Package observed Oct 10, 2026.
Technical details
- First seen
- Sep 30, 2026 · 22:02 UTC
- Last seen
- Oct 10, 2026 · 18:00 UTC
- Collection status
- Collected
plugin_asdk_app_6a9a3c1cd0108191807da33c4cd319ed
Download plugin data (JSON)Plugin details: served from cache. Prepared . Refreshed when plugin data changes or after 6 hours. Your account and Follow status are live.