llms.txt
llms.txt

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

farm add integration clerk --ui

Configure

src/lib/integrations.ts
import { clerk } from "@farm.js/integrations/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 and @clerk/backend in the application. 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(...).

import { createClerkClient } from "@clerk/backend";import { clerk } from "@farm.js/integrations/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
"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:

"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

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:

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:

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.