---
title: "Clerk Integration"
description: "Register ClerkProvider and protect Farm routes with Clerk request authentication."
canonical_url: "https://farmjs.dev/docs/integrations/auth/clerk"
markdown_url: "https://farmjs.dev/docs/integrations/auth/clerk.md"
last_updated: "2026-11-03"
x_farming_labs_generated_preamble: true
---

# Clerk Integration
URL: /docs/integrations/auth/clerk
LLM index: /llms.txt
Description: Register ClerkProvider and protect Farm routes with Clerk request authentication.

# Clerk Integration

The Clerk integration connects Clerk's React and backend SDKs to the Farm runtime. Farm wraps the app in `ClerkProvider` and can authenticate matched requests, while Clerk remains responsible for UI, users, sessions, organizations, and account flows.

Farm does not create Clerk login, callback, session, or logout API routes.

## Add Clerk

**Terminal**

```bash
farm add integration clerk --ui
```

## Configure

**src/lib/integrations.ts**

```ts
import { clerk } from "@farm.js/clerk";

export const appIntegrations = {
  auth: clerk({
    publishableKey: process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY,
    secretKey: process.env.CLERK_SECRET_KEY,
    signInUrl: "/sign-in",
    signUpUrl: "/sign-up",
    protectedRoutes: ["/dashboard(.*)"],
  }),
} as const;
```

The keys can be omitted from the call when the environment variables are set.

## Environment variables

| Variable                            | Required    | Purpose                                            |
| ----------------------------------- | ----------- | -------------------------------------------------- |
| `NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY` | Yes         | Preferred publishable key name.                    |
| `CLERK_PUBLISHABLE_KEY`             | Alternative | Fallback environment name for the publishable key. |
| `CLERK_SECRET_KEY`                  | Yes         | Used by `@clerk/backend` to authenticate requests. |

Install `@clerk/react` in the application. `@farm.js/clerk` already depends on `@clerk/backend`, so add it to the application only when the application constructs its own backend client, as shown below. Farm loads the React provider at render time and the backend client inside protected-route middleware.

## Choose SDK ownership

### Let Farm construct Clerk

The configuration above is the default path. When `instance` is omitted, Farm lazily creates one
Clerk backend client from `publishableKey` and `secretKey`. Both values may be passed directly or
read from the documented environment variables.

### Provide an application-owned instance

Pass a backend client through `instance` to keep Clerk construction and version-specific options in
application code. The publishable key is still required for `ClerkProvider`; the secret key is not
required by Farm when the backend instance is supplied.

When both an instance and construction credentials are present, the instance wins. Farm-owned
options such as `protectedRoutes`, `providerProps`, and sign-in URLs still belong in `clerk(...)`.

```ts
import { createClerkClient } from "@clerk/backend";
import { clerk } from "@farm.js/clerk";

const clerkClient = createClerkClient({
  secretKey: process.env.CLERK_SECRET_KEY,
  publishableKey: process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY,
});

export const auth = clerk({
  instance: clerkClient,
  publishableKey: process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY,
  protectedRoutes: ["/dashboard(.*)"],
});
```

## Create sign-in and sign-up pages

`signInUrl` and `signUpUrl` tell Farm where your Clerk pages live. They do not create those pages.

**src/app/sign-in/[...clerk]/page.tsx**

```tsx
"use client";

import { SignIn } from "@clerk/react";

export default function SignInPage() {
  return (
    <SignIn path="/sign-in" routing="path" signUpUrl="/sign-up" fallbackRedirectUrl="/dashboard" />
  );
}
```

Create the matching sign-up page with Clerk's `SignUp` component.

## Use Clerk in the app

Because Farm registers `ClerkProvider`, client components can use Clerk directly:

```tsx
"use client";

import { SignedIn, SignedOut, SignInButton, UserButton } from "@clerk/react";

export function AccountMenu() {
  return (
    <>
      <SignedOut>
        <SignInButton />
      </SignedOut>
      <SignedIn>
        <UserButton />
      </SignedIn>
    </>
  );
}
```

Use Clerk's hooks and backend APIs for session, user, and organization data. There is no `api.auth.session` operation for this integration.

## Protect app routes

```ts
clerk({
  signInUrl: "/sign-in",
  protectedRoutes: ["/dashboard(.*)", "/settings(.*)"],
});
```

For a matched request, Farm calls `authenticateRequest` from `@clerk/backend`:

- authenticated requests continue to the page or API handler;
- Clerk handshake and cookie responses are forwarded;
- signed-out requests receive a `307` redirect to `signInUrl`;
- the original pathname is sent as Clerk's `redirect_url`.

## Authorized parties

By default, Clerk accepts the current request origin as an authorized party. Set an explicit list when the app has multiple trusted origins:

```ts
clerk({
  authorizedParties: ["https://app.example.com", "https://admin.example.com"],
});
```

This is especially useful when protecting against cookie misuse across sibling domains.

## Provider props

Pass additional `ClerkProvider` props through `providerProps`:

```ts
clerk({
  providerProps: {
    appearance: {
      variables: {
        colorPrimary: "#111111",
      },
    },
  },
});
```

`publishableKey` is supplied automatically and can still be combined with these props.

## Options

| Option              | Default                   | Use                                               |
| ------------------- | ------------------------- | ------------------------------------------------- |
| `instance`          | None                      | Existing Clerk backend client.                    |
| `publishableKey`    | Clerk publishable key env | Client-safe Clerk key.                            |
| `secretKey`         | `CLERK_SECRET_KEY`        | Server Clerk key when no instance is supplied.    |
| `signInUrl`         | `/sign-in`                | App-owned Clerk sign-in page.                     |
| `signUpUrl`         | `/sign-up`                | App-owned Clerk sign-up page.                     |
| `protectedRoutes`   | None                      | One matcher or a list of matchers.                |
| `authorizedParties` | Current origin            | Origins accepted by Clerk request authentication. |
| `providerProps`     | `{}`                      | Additional props for `ClerkProvider`.             |

## Production checklist

- Keep `CLERK_SECRET_KEY` out of client code.
- Configure Clerk's allowed origins and redirect URLs.
- Create both sign-in and sign-up catch-all pages.
- Test Clerk handshake redirects as well as normal signed-out redirects.
- Verify organization switching on every tenant-scoped route.

## Sitemap

See the full [sitemap](/sitemap.md) for all pages.
Docs-scoped sitemap: [/docs/sitemap.md](/docs/sitemap.md).
Well-known sitemap: [/.well-known/sitemap.md](/.well-known/sitemap.md).
