# Better Auth (with Astro) (/docs/guides/authentication/better-auth/astro)
> For the complete Prisma documentation index, see [llms.txt](https://www.prisma.io/docs/llms.txt). A markdown version of any docs page is available by appending `.md` to its URL.
Learn how to use Prisma ORM in an Astro app with Better Auth
Location: Guides > Authentication > Better Auth > Better Auth (with Astro)
> [!NOTE]
> This guide uses Prisma ORM 7
>
> The commands and code on this page target Prisma ORM 7, which remains fully supported. To start a new Prisma ORM 8 project, see [Create a new app with PostgreSQL](https://www.prisma.io/docs/prisma-orm/quickstart/postgresql); to add Prisma ORM 8 to an existing app, see [Add Prisma ORM to an existing PostgreSQL database](https://www.prisma.io/docs/prisma-orm/add-to-existing-project/postgresql). A Prisma ORM 8 version of this guide is not available yet: Better Auth's `prismaAdapter` requires Prisma Client, which Prisma ORM 8 replaces with the `@prisma/orm-postgres` runtime.
## Introduction [#introduction]
[Better Auth](https://better-auth.com/) is an open-source authentication library for web apps. It's written in TypeScript, can be extended with plugins, and supports multiple database adapters, including Prisma.
In this guide, you'll wire Better Auth into a brand-new [Astro](https://astro.build/) app and persist users in a [Prisma Postgres](https://prisma.io/postgres) database. You can find a complete example of this guide on [GitHub](https://github.com/prisma/prisma-examples/tree/latest/orm/betterauth-astro).
## Prerequisites [#prerequisites]
* [Node.js 22.12+ on 22.x or 24+](https://nodejs.org)
* Basic familiarity with Astro and Prisma
## 1. Set up your project [#1-set-up-your-project]
Create a new Astro project:
#### bun
```bash
bunx create-astro betterauth-astro-prisma
```
#### pnpm
```bash
pnpm create astro betterauth-astro-prisma
```
#### yarn
```bash
yarn create astro betterauth-astro-prisma
```
#### npm
```bash
npm create astro@latest betterauth-astro-prisma
```
> [!NOTE]
> * *How would you like to start your new project?* `Use minimal (empty) template `
> * *Install dependencies? (recommended)* `Yes`
> * *Initialize a new git repository? (optional)* `Yes`
Navigate to the project directory:
```bash
cd betterauth-astro-prisma
```
These selections will create a minimal Astro project with TypeScript for type safety.
## 2. Set up Prisma [#2-set-up-prisma]
Next, you'll add Prisma to your project to manage your database.
### 2.1. Install Prisma and dependencies [#21-install-prisma-and-dependencies]
Install the necessary Prisma packages:
#### bun
```bash
bun add prisma@prev tsx @types/pg --dev
```
#### pnpm
```bash
pnpm add prisma@prev tsx @types/pg --save-dev
```
#### yarn
```bash
yarn add prisma@prev tsx @types/pg --dev
```
#### npm
```bash
npm install prisma@prev tsx @types/pg --save-dev
```
#### bun
```bash
bun add @prisma/client@7 @prisma/adapter-pg dotenv pg
```
#### pnpm
```bash
pnpm add @prisma/client@7 @prisma/adapter-pg dotenv pg
```
#### yarn
```bash
yarn add @prisma/client@7 @prisma/adapter-pg dotenv pg
```
#### npm
```bash
npm install @prisma/client@7 @prisma/adapter-pg dotenv pg
```
> [!NOTE]
> If you are using a different database provider (MySQL, SQL Server, SQLite), install the corresponding driver adapter package instead of `@prisma/adapter-pg`. For more information, see [Database drivers](https://www.prisma.io/docs/orm/v7/core-concepts/supported-databases/database-drivers).
Once installed, initialize Prisma in your project:
#### bun
```bash
bunx --bun prisma init --output ../prisma/generated
```
#### pnpm
```bash
pnpm prisma init --output ../prisma/generated
```
#### yarn
```bash
yarn prisma init --output ../prisma/generated
```
#### npm
```bash
npx prisma init --output ../prisma/generated
```
> [!NOTE]
> `prisma init` creates the Prisma scaffolding and a local `DATABASE_URL`. In the next step, you will create a Prisma Postgres database and replace that value with a direct `postgres://...` connection string.
This will create:
* A `prisma` directory with a `schema.prisma` file
* A `.env` file containing a local `DATABASE_URL` at the project root
* A `prisma.config.ts` file for configuring Prisma
* An `output` directory for the generated Prisma Client as `prisma/generated`
Create a Prisma Postgres database and replace the generated `DATABASE_URL` in your `.env` file with the `postgres://...` connection string from the CLI output:
#### bun
```bash
bunx create-db
```
#### pnpm
```bash
pnpm dlx create-db
```
#### yarn
```bash
yarn dlx create-db
```
#### npm
```bash
npx create-db
```
### 2.2. Configure Prisma to load environment variables [#22-configure-prisma-to-load-environment-variables]
To get access to the variables in the `.env` file, update your `prisma.config.ts` to import `dotenv`:
```ts title="prisma.config.ts" showLineNumbers
import "dotenv/config"; // [!code ++]
import { defineConfig, env } from "prisma/config";
export default defineConfig({
schema: "prisma/schema.prisma",
migrations: {
path: "prisma/migrations",
},
engine: "classic",
datasource: {
url: env("DATABASE_URL"),
},
});
```
### 2.3. Generate the Prisma Client [#23-generate-the-prisma-client]
Run the following command to generate the Prisma Client:
#### bun
```bash
bunx prisma generate
```
#### pnpm
```bash
pnpm prisma generate
```
#### yarn
```bash
yarn prisma generate
```
#### npm
```bash
npx prisma generate
```
### 2.4. Set up a global Prisma client [#24-set-up-a-global-prisma-client]
In the `src` directory, create a `lib` folder and a `prisma.ts` file inside it. This file will be used to create and export your Prisma Client instance.
```bash
mkdir -p src/lib
touch src/lib/prisma.ts
```
Set up the Prisma client like this:
```ts title="src/lib/prisma.ts"
import { PrismaClient } from "../../prisma/generated/client";
import { PrismaPg } from "@prisma/adapter-pg";
const adapter = new PrismaPg({
connectionString: import.meta.env.DATABASE_URL,
});
const prisma = new PrismaClient({
adapter,
});
export default prisma;
```
> [!WARNING]
> We recommend using a connection pooler (like [Prisma Accelerate](https://www.prisma.io/accelerate)) to manage database connections efficiently.
>
> If you choose not to use one, **avoid** instantiating `PrismaClient` globally in long-lived environments. Instead, create and dispose of the client per request to prevent exhausting your database connections.
## 3. Set up Better Auth [#3-set-up-better-auth]
Next, add Better Auth to handle sign-up, sign-in, and sessions.
### 3.1. Install and configure Better Auth [#31-install-and-configure-better-auth]
First, install the Better Auth core package:
#### bun
```bash
bun add better-auth
```
#### pnpm
```bash
pnpm add better-auth
```
#### yarn
```bash
yarn add better-auth
```
#### npm
```bash
npm install better-auth
```
Next, generate a secure secret that Better Auth will use to sign authentication tokens. This ensures your tokens cannot be tampered with.
#### bun
```bash
bunx @better-auth/cli@latest secret
```
#### pnpm
```bash
pnpm dlx @better-auth/cli@latest secret
```
#### yarn
```bash
yarn dlx @better-auth/cli@latest secret
```
#### npm
```bash
npx @better-auth/cli@latest secret
```
Copy the generated secret and add it, along with your application's URL, to your `.env` file:
```bash title=".env"
# Better Auth
BETTER_AUTH_SECRET=your-generated-secret # [!code ++]
BETTER_AUTH_URL=http://localhost:4321 # [!code ++]
# Prisma
DATABASE_URL="your-database-url"
```
> [!NOTE]
> Astro's default development server runs on port `4321`. If your application runs on a different port, update the `BETTER_AUTH_URL` accordingly.
Now, create a configuration file for Better Auth. In the `src/lib` directory, create an `auth.ts` file:
```bash
touch src/lib/auth.ts
```
In this file, you'll configure Better Auth to use the Prisma adapter, which allows it to persist user and session data in your database. You will also enable email and password authentication.
```ts title="src/lib/auth.ts"
import { betterAuth } from "better-auth";
import { prismaAdapter } from "better-auth/adapters/prisma";
import prisma from "./prisma";
export const auth = betterAuth({
database: prismaAdapter(prisma, {
provider: "postgresql",
}),
emailAndPassword: {
enabled: true,
},
});
```
Better Auth also supports other sign-in methods like social logins (Google, GitHub, etc.), which you can explore in their [email and password documentation](https://www.better-auth.com/docs/authentication/email-password).
### 3.2. Add Better Auth models to your schema [#32-add-better-auth-models-to-your-schema]
Better Auth provides a CLI command to automatically add the necessary authentication models (`User`, `Session`, `Account`, and `Verification`) to your `schema.prisma` file.
Run the following command:
#### bun
```bash
bunx @better-auth/cli generate
```
#### pnpm
```bash
pnpm dlx @better-auth/cli generate
```
#### yarn
```bash
yarn dlx @better-auth/cli generate
```
#### npm
```bash
npx @better-auth/cli generate
```
> [!NOTE]
> It will ask for confirmation to overwrite your existing Prisma schema. Select `y`.
This will add the following models:
```prisma
model User {
id String @id
name String
email String
emailVerified Boolean
image String?
createdAt DateTime
updatedAt DateTime
sessions Session[]
accounts Account[]
@@unique([email])
@@map("user")
}
model Session {
id String @id
expiresAt DateTime
token String
createdAt DateTime
updatedAt DateTime
ipAddress String?
userAgent String?
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@unique([token])
@@map("session")
}
model Account {
id String @id
accountId String
providerId String
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
accessToken String?
refreshToken String?
idToken String?
accessTokenExpiresAt DateTime?
refreshTokenExpiresAt DateTime?
scope String?
password String?
createdAt DateTime
updatedAt DateTime
@@map("account")
}
model Verification {
id String @id
identifier String
value String
expiresAt DateTime
createdAt DateTime?
updatedAt DateTime?
@@map("verification")
}
```
### 3.3. Migrate the database [#33-migrate-the-database]
With the new models in your schema, you need to update your database. Run a migration to create the corresponding tables:
#### bun
```bash
bunx prisma migrate dev --name add-auth-models
```
#### pnpm
```bash
pnpm prisma migrate dev --name add-auth-models
```
#### yarn
```bash
yarn prisma migrate dev --name add-auth-models
```
#### npm
```bash
npx prisma migrate dev --name add-auth-models
```
#### bun
```bash
bunx prisma generate
```
#### pnpm
```bash
pnpm prisma generate
```
#### yarn
```bash
yarn prisma generate
```
#### npm
```bash
npx prisma generate
```
## 4. Set up the API routes [#4-set-up-the-api-routes]
Better Auth needs an API endpoint to handle authentication requests like sign-in, sign-up, and sign-out. You'll create a catch-all API route in Astro to handle all requests sent to `/api/auth/[...all]`.
In the `src/pages` directory, create an `api/auth` folder structure and a `[...all].ts` file inside it:
```bash
mkdir -p src/pages/api/auth
touch 'src/pages/api/auth/[...all].ts'
```
Add the following code to the newly created `[...all].ts` file. This code uses the Better Auth handler to process authentication requests.
```ts title="src/pages/api/auth/[...all].ts"
import { auth } from "../../../lib/auth";
import type { APIRoute } from "astro";
export const prerender = false; // Not needed in 'server' mode
export const ALL: APIRoute = async (ctx) => {
return auth.handler(ctx.request);
};
```
Next, you'll need a client-side utility to interact with these endpoints from your Astro pages. In the `src/lib` directory, create an `auth-client.ts` file:
```bash
touch src/lib/auth-client.ts
```
Add the following code, which creates the client functions you'll use in your UI:
```ts title="src/lib/auth-client.ts"
import { createAuthClient } from "better-auth/client";
export const authClient = createAuthClient();
export const { signIn, signUp, signOut, useSession } = authClient;
```
## 5. Configure TypeScript definitions [#5-configure-typescript-definitions]
In the `src` directory, create an `env.d.ts` file to provide TypeScript definitions for environment variables and Astro locals:
```bash
touch src/env.d.ts
```
Add the following type definitions:
```ts title="src/env.d.ts"
///
Already have an account? Sign in here.
// [!code ++]Already have an account? Sign in here.
Already have an account? Sign in here.
Don't have an account? Sign up here.
// [!code ++]Don't have an account? Sign up here.
Don't have an account? Sign up here.
{JSON.stringify(Astro.locals.user, null, 2)}
// [!code ++]
{JSON.stringify(Astro.locals.user, null, 2)}
// [!code ++]
Welcome back, {Astro.locals.user.name}!
Go to Dashboard