- Published on
Tanstack Start Better Auth Setup
- Authors

- Name
- adk
- @andrewdavidkay
Install NPM Package
Terminal
npm install better-auth@latest
Set Enviornment Variables
Generate the key with openssl.
Terminal
openssl rand -base64 32
Then set the environment variable.
.env
BETTER_AUTH_SECRET=<generated secret key>
Set the base URL.
.env
BETTER_AUTH_URL=http://localhost:3000
Create An Instance
src/lib/auth.ts
import { betterAuth } from "better-auth";
export const auth = betterAuth({
//...
});
Add the Drizzle adapter.
src/lib/auth.ts
import { betterAuth } from "better-auth";
import { drizzleAdapter } from "better-auth/adapters/drizzle";
import { db } from "@/db";
export const auth = betterAuth({
database: drizzleAdapter(db, {
provider: "pg",
}),
});
Schema
I'm going to do some restructuring of the schema files to so that I can have a separate schema file for each model or use case such as auth.
Terminal
mkdir src/db/schema
touch src/db/schema/index.ts
touch src/db/schema/auth.schema.ts
echo 'export * from "./auth.schema.ts";' > src/db/schema/index.ts
rm src/db/schema.ts
Update src/db/index.ts.
src/db/index.ts
import { config } from "dotenv";
import { drizzle } from "drizzle-orm/node-postgres";
import { Pool } from "pg";
import * as schema from "./schema";
config();
const pool = new Pool({
connectionString: process.env.DATABASE_URL!,
});
export const db = drizzle(pool, { schema });
Update Drizzle config.
drizzle.config.ts
import { config } from 'dotenv'
import { defineConfig } from 'drizzle-kit'
config()
export default defineConfig({
out: './drizzle',
schema: './src/db/schema',
dialect: 'postgresql',
dbCredentials: {
url: process.env.DATABASE_URL,
},
})
Generate the required Better Auth schema.
Terminal
npx @better-auth/cli@latest generate --config ./src/lib/auth.ts -y --output ./src/db/schema/auth.schema.ts && prettier --write ./src/db/schema/auth.schema.ts
Delete the demo folder because todos schema no longer exists.
Terminal
rm -rf src/routes/demo
Generate the migration file.
Terminal
npx drzzle-kit generate
Run the migration.
Terminal
npx drizzle-kit migrate
Authentication Method
For this app I'm going to be using email and password authentication.
src/lib/auth.ts
import { betterAuth } from "better-auth";
import { drizzleAdapter } from "better-auth/adapters/drizzle";
import { db } from "@/db";
export const auth = betterAuth({
database: drizzleAdapter(db, {
provider: "pg",
}),
emailAndPassword: {
enabled: true,
},
});
Mount Handler
Create a catch-all api route for Better Auth.
Terminal
mkdir -p src/routes/api/auth && touch src/routes/api/auth/$.ts
src/routes/api/auth/$.ts
import { createFileRoute } from "@tanstack/react-router";
import { auth } from "@/lib/auth";
export const Route = createFileRoute("/api/auth/$")({
server: {
handlers: {
GET: async ({ request }: { request: Request }) => {
return await auth.handler(request);
},
POST: async ({ request }: { request: Request }) => {
return await auth.handler(request);
},
},
},
});
Create Client Instance
Create a new file src/lib/auth-client.ts.
Terminal
touch src/lib/auth-client.ts`
```typescript:src/lib/auth-client.ts
import { createAuthClient } from "better-auth/react"
export const authClient = createAuthClient({})
Usage
src/lib/auth.ts
import { betterAuth } from "better-auth";
import { drizzleAdapter } from "better-auth/adapters/drizzle";
import { tanstackStartCookies } from "better-auth/tanstack-start";
import { db } from "@/db";
export const auth = betterAuth({
database: drizzleAdapter(db, {
provider: "pg",
}),
emailAndPassword: {
enabled: true,
},
plugins: [tanstackStartCookies()], // make sure this is the last plugin in the array
});
Git Commit
Terminal
git add .
git commit -am 'inital better auth setup'