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

Loading the lesson…
Loading activities…
AUTHENTICATION / LESSON 06
Install Better Auth in a Next.js app and connect it to your own database

Loading the lesson…
Loading activities…
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.
You need two things ready to go.
app/ folder)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.
In your project folder, run this.
That adds Better Auth to your project, same as any other npm package.
Make a .env file in the root of your project. Better Auth needs two values in there.
BETTER_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.
Paste 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.
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.
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.
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.
Then 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.
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.
Now tell Better Auth how people get in. Keep it simple and start with email and password.
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.
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.
Migrate creates the tables directly in your database.
So 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.
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.
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.
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.
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.
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 |
npm install better-auth.BETTER_AUTH_SECRET (at least 32 random characters) and BETTER_AUTH_URL in .env.auth.ts with betterAuth, connect your database, and turn on emailAndPassword.npx auth@latest generate or, for the built-in Kysely adapter, npx auth@latest migrate.toNextJsHandler(auth) at app/api/auth/[...all]/route.ts.createAuthClient from better-auth/react.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.