Co-authored by
Hayden Bleaselnext-forge
Bereket EngidaBetter Auth

Better Auth is a comprehensive, open-source authentication framework for TypeScript. It is designed to be framework agnostic, but integrates well with Next.js and provides a lot of features out of the box.

1. Swap out the auth package dependencies

Uninstall the existing Clerk dependencies from the auth package…

Terminal
pnpm remove @clerk/nextjs @clerk/themes @clerk/types --filter @repo/auth

…and install the Better Auth dependencies:

Terminal
pnpm add better-auth @repo/database --filter @repo/auth

2. Update your environment variables

Generate a secret with the following command to add it to the .env.local file in each Next.js application (app, web and api):

Terminal
npx @better-auth/cli secret

This will add a BETTER_AUTH_SECRET environment variable to the .env.local file.

3. Setup the server and client auth

Update the auth package files with the following code:

Read more in the Better Auth installation guide.

4. Update the auth components

Update both the sign-in.tsx and sign-up.tsx components in the auth package to use the signIn and signUp functions from the client file.

You can use different sign-in methods like social providers, phone, username etc. Read more about Better Auth basic usage.

5. Generate Prisma Models

From the root folder, generate Prisma models for Better Auth by running the following command:

Terminal
npx @better-auth/cli generate --output ./packages/database/prisma/schema.prisma --config ./packages/auth/server.ts

You may have to comment out the server-only directive in packages/database/index.ts temporarily. Ensure you have environment variables set.

Best practice is to have a better-auth.ts file, but we’re just specifying the existing server.ts left over from Clerk here.

6. Update the Provider file

Better Auth has no concept of a Provider as a higher-order component, so you can either remove it entirely or just replace it with a stub, like so:

packages/auth/provider.tsx
import type { ReactNode } from 'react';

type AuthProviderProps = {
  children: ReactNode;
};

export const AuthProvider = ({ children }: AuthProviderProps) => children;

7. Change Middleware

Change the middleware in the auth package to the following:

packages/auth/middleware.ts
import { NextRequest } from "next/server";
import { createAuthClient } from "better-auth/client";

const { getSession } = createAuthClient();

const isProtectedRoute = (request: NextRequest) => {
  return request.url.startsWith("/dashboard"); // change this to your protected route
}

export const authMiddleware = async (request: NextRequest) => {
  const session = await getSession(request);
  
  if (isProtectedRoute(request) && !session) {
    return NextResponse.redirect(new URL("/sign-in", request.url));
  }
  
  return NextResponse.next();
}

8. Update your apps

From here, you’ll need to replace any remaining Clerk implementations in your apps with Better Auth.

Here is some inspiration:

const user = await currentUser();
const { redirectToSignIn } = await auth();

// to

const session = await auth.api.getSession({
  headers: await headers(), // from next/headers
});
if (!session?.user) {
  return redirect('/sign-in'); // from next/navigation
}
// do something with session.user
const { orgId } = await auth();

// to

const h = await headers(); // from next/headers
const session = await auth.api.getSession({
  headers: h,
});
const orgId = session?.session.activeOrganizationId;
const fullOrganization = await auth.api.getFullOrganization({
  headers: h,
  query: { organizationId: orgId },
});
webhooks/stripe/route.ts
import { clerkClient } from '@repo/auth/server';

const clerk = await clerkClient();
const users = await clerk.users.getUserList();
const user = users.data.find(
  (user) => user.privateMetadata.stripeCustomerId === customerId
);

// to

import { database } from '@repo/database';

const user = await database.user.findFirst({
  where: {
    privateMetadata: {
      contains: { stripeCustomerId: customerId },
    },
  },
});

For using organization, check organization plugin and more from the Better Auth documentation.