Create FasterCreate Faster
Auth

Better Auth

Pre-configured authentication with ORM adapter integration, API routes, and shared auth package for monorepos.

Supported frameworks
Dependencies

→ Better Auth Documentation

Requirements: Database + ORM (Drizzle or Prisma)

What create-faster adds

Files added:

src/
├── lib/auth/
│   ├── auth.ts              # Server auth config
│   └── auth-client.ts       # Client auth helpers
└── app/api/auth/[...all]/
    └── route.ts             # Auth API handler

# Turborepo only:
packages/auth/
├── src/
│   ├── auth.ts
│   ├── auth-client.ts
│   ├── route.ts
│   └── types.ts
├── package.json             # @repo/auth
└── tsconfig.json

Environment variables:

  • BETTER_AUTH_SECRET - Auth secret key (scoped to auth package + app)
  • BETTER_AUTH_URL - Auth URL (scoped to app)

auth.ts

Server-side auth configuration with ORM adapter. Shown here with Drizzle + PostgreSQL:

src/lib/auth/auth.ts
import { db, userAccountTable, userSessionTable, userTable, userVerificationTable } from '@/lib/db';
import { drizzleAdapter } from 'better-auth/adapters/drizzle';
import { betterAuth } from 'better-auth';
import { nextCookies } from 'better-auth/next-js';

const HOUR = 60 * 60;
const DAY = 24 * HOUR;

export const auth = betterAuth({
  database: drizzleAdapter(db, {
    provider: 'pg',
    usePlural: false,
    schema: {
      user: userTable,
      account: userAccountTable,
      session: userSessionTable,
      verification: userVerificationTable,
    },
  }),

  plugins: [nextCookies()],
  emailAndPassword: {
    enabled: true,
    minPasswordLength: 6,
    revokeSessionsOnPasswordReset: true,
  },
  user: {
    modelName: 'user',
    fields: {
      name: 'username',
      email: 'email',
      emailVerified: 'emailVerified',
      image: 'avatarUrl',
      createdAt: 'createdAt',
      updatedAt: 'updatedAt',
    },
  },
  session: {
    modelName: 'session',
    expiresIn: 15 * DAY,
  },
  account: { modelName: 'account' },
  verification: { modelName: 'verification' },
});

Adapts automatically based on ORM and database selection:

  • Drizzle: Uses drizzleAdapter with pg or mysql provider
  • Prisma: Uses prismaAdapter with postgresql or mysql provider

auth-client.ts

Client-side auth helpers with type inference:

src/lib/auth/auth-client.ts
import { inferAdditionalFields } from 'better-auth/client/plugins';
import { createAuthClient } from 'better-auth/react';
import type { auth } from './auth';

export const authClient = createAuthClient({
  baseURL: process.env.BETTER_AUTH_URL || process.env.NEXT_PUBLIC_BETTER_AUTH_URL,
  plugins: [inferAdditionalFields<typeof auth>()],
});

route.ts

Next.js API route handler:

src/app/api/auth/[...all]/route.ts
import { toNextJsHandler } from 'better-auth/next-js';
import { auth } from '@/lib/auth/auth';

export const { GET, POST } = toNextJsHandler(auth.handler);

In turborepo mode, the app re-exports from @repo/auth/route-nextjs instead.

Turborepo mode: Creates @repo/auth package depending on @repo/db for database access. Auth config lives in the package, app imports handlers.

On this page