Setting Up Better Auth
Install Better Auth in a Next.js app and connect it to your own database

Buzz presents
one install, one secret, one little auth file, and a few more steps. we set up Better Auth together, no worries at all!one install, one secret, one little auth file, and a few more steps. we set up Better Auth together, no worries at all!

Time to actually set up Better Auth in a Next.js app, following the steps from the official installation guide. By the end you'll have a secret key, an auth file, database tables, a route that handles login requests and a client your pages can call. Sounds like a lot... it's mostly copy and paste.
Before You Start#
You need two things ready to go.
- A Next.js project using the App Router (the
app/folder) - A database you can connect to, such as PostgreSQL, MySQL or SQLite
Everything below matches the Better Auth installation guide. The commands are shown with npm, and the docs list the pnpm, yarn and bun versions too.
Installing Better Auth#
Step 1. Install the Package#
In your project folder, run this.
npm install better-authThat adds Better Auth to your project, same as any other npm package.
Step 2. Set Your Environment Variables#
Make a .env file in the root of your project. Better Auth needs two values in there.
BETTER_AUTH_SECRET=
BETTER_AUTH_URL=http://localhost:3000BETTER_AUTH_SECRET is a secret value used for encryption and hashing. The docs say it has to be at least 32 characters and generated with high entropy, which is a fancy way of saying truly random. The installation page has a button that generates one for you, or you can run this in your terminal.
openssl rand -base64 32Paste whatever it spits out right after the equals sign.
BETTER_AUTH_URL is the base URL of your app. While you're building locally, that's http://localhost:3000. Once you go live, it becomes your real website address.
Step 3. Create the Auth Instance#
Next up, create a file named auth.ts. The docs say it can live in the project root, a lib/ folder or a utils/ folder, and those folders can sit inside src/, app/ or server/. This lesson goes with lib/auth.ts.
// lib/auth.ts
import { betterAuth } from "better-auth";
export const auth = betterAuth({
//...
});The docs say to export it with the name auth or as a default export. This auth object is the server side of Better Auth, and everything else plugs into it.
Step 4. Connect Your Database#
Better Auth keeps users and sessions in your database, so you have to tell it how to reach that database. Here's the PostgreSQL version, based on the example from the PostgreSQL adapter page.
This example uses the pg package to talk to PostgreSQL, so install that first, along with its TypeScript types.
npm install pg
npm install -D @types/pgThen add your database's connection string to that same .env file as DATABASE_URL. Swap in the user, password, host and database name for your own.
DATABASE_URL=postgres://user:password@localhost:5432/database// lib/auth.ts
import { betterAuth } from "better-auth";
import { Pool } from "pg";
export const auth = betterAuth({
database: new Pool({
connectionString: process.env.DATABASE_URL,
}),
})The connection string gets read from DATABASE_URL, so the password stays in .env and OUT of your code. The adapter page's own example pastes the string straight in. That's fine for a quick test, but it's really easy to commit by accident (and once a password lands somewhere public, the only fix is changing it).
The docs show matching examples for SQLite (using better-sqlite3) and MySQL (using mysql2/promise). If you already use an ORM, there are built-in adapters for that instead. Prisma users import prismaAdapter from better-auth/adapters/prisma, for example, and Drizzle users import drizzleAdapter from better-auth/adapters/drizzle.
Step 5. Turn On a Sign In Method#
Now tell Better Auth how people get in. Keep it simple and start with email and password.
// lib/auth.ts
import { betterAuth } from "better-auth";
import { Pool } from "pg";
export const auth = betterAuth({
database: new Pool({
connectionString: process.env.DATABASE_URL,
}),
emailAndPassword: {
enabled: true,
},
})You can add social providers the same way later on. The docs show GitHub added under socialProviders, using a client ID and secret stored in your environment variables.
Step 6. Create the Database Tables#
Better Auth ships with a command line tool (CLI) that already knows which tables it needs. There are two commands.
Generate creates a schema file or SQL migration file for you to apply.
npx auth@latest generateMigrate creates the tables directly in your database.
npx auth@latest migrateSo which one do you use? The docs say migrate is only available for the built-in Kysely adapter. The PostgreSQL adapter page explains that PostgreSQL "is supported under the hood via the Kysely adapter", which means the direct Pool setup above is using it. That's why the same page lists both generate and migrate as supported, and migrate is the quick option here. If you're on Prisma or Drizzle, run generate and then apply the change with your ORM's own migration tool.
Connecting It to Next.js#
Step 7. Mount the Route Handler#
Your app needs a URL that receives login requests. By default Better Auth uses paths that start with /api/auth/. In the App Router, create this file.
// app/api/auth/[...all]/route.ts
import { auth } from "@/lib/auth"; // path to your auth file
import { toNextJsHandler } from "better-auth/next-js";
export const { POST, GET } = toNextJsHandler(auth);That [...all] folder name is a Next.js catch-all route. It sends every request under /api/auth/ to Better Auth, so sign up, sign in and sign out ALL run through this one file.
Step 8. Create the Client Instance#
Last piece. The client is what your pages use to talk to the route you just made. For React and Next.js, import it from better-auth/react.
// lib/auth-client.ts
import { createAuthClient } from "better-auth/react"
export const authClient = createAuthClient({
/** The base URL of the server (optional if you're using the same domain) */
baseURL: "http://localhost:3000"
})The docs say you can skip baseURL when your auth server runs on the same domain as your pages, which is the usual setup in a Next.js app.
What You Built#

Here's how all the pieces fit together.
| File | Job |
|---|---|
.env | Holds the secret, the base URL and the database connection string |
lib/auth.ts | The server side setup, including the database and sign in methods |
app/api/auth/[...all]/route.ts | Receives login requests at /api/auth/ |
lib/auth-client.ts | Lets your pages sign users up, in and out |
TL;DR#
- Install with
npm install better-auth. - Set
BETTER_AUTH_SECRET(at least 32 random characters) andBETTER_AUTH_URLin.env. - Create
auth.tswithbetterAuth, connect your database, and turn onemailAndPassword. - Create tables with
npx auth@latest generateor, for the built-in Kysely adapter,npx auth@latest migrate. - Mount
toNextJsHandler(auth)atapp/api/auth/[...all]/route.ts. - Create the client with
createAuthClientfrombetter-auth/react.
What's Next?#
Everything's wired up. In the next lesson you'll use authClient to sign users up, sign them in and out, read the session and protect a page.
This lesson ends with a short activity.
