Nuxt Better Auth Utilities
nuxt-better-auth-utils is a Nuxt module providing a full lifecycle integration for the Better Auth library, offering auto-wired API handlers, SSR session pre-fetching, and typed server/client APIs. It's currently at version 0.1.27 and has a rapid release cadence with frequent bug fixes and minor improvements, often multiple releases per week. Key differentiators include its tight integration with Nuxt's SSR capabilities, providing reactive session state via `useAuth()` on the client and `useServerAuth()` for server-side operations, and automatic type inference. It remains database-agnostic, deferring to Better Auth's adapter ecosystem. This module aims to simplify authentication setup in Nuxt applications by handling much of the boilerplate, including API routing, session management, and protecting pages with middleware, without imposing opinions on the underlying authentication strategy or data storage.
Common errors
-
Cannot find name 'useAuth'. Did you mean 'Auth'?
cause Nuxt auto-imports are not correctly registered or processed.fixEnsure `nuxt-better-auth-utils` is correctly listed in your `nuxt.config.ts` modules array. Restart your Nuxt development server. Check for any `tsconfig.json` misconfigurations. -
Error: [nuxt] `betterAuthUtils` module options are not defined in `nuxt.config.ts`.
cause The module itself is not added to the `modules` array in `nuxt.config.ts`.fixAdd `'nuxt-better-auth-utils'` to the `modules` array in your `nuxt.config.ts`. -
TypeError: Cannot read properties of undefined (reading 'user') in useServerAuth
cause Attempting to access `session.user` when `session` is `null` because the user is unauthenticated, and `getSession` was used instead of `requireSession`.fixUse `requireSession(event)` if an authenticated user is strictly required (it throws an error for unauthenticated requests), or defensively check `if (session) { /* ... */ }` after `getSession(event)`. -
Error: 'BETTER_AUTH_SECRET' environment variable is not set.
cause The mandatory secret environment variable is missing.fixSet `BETTER_AUTH_SECRET` in your `.env` file (e.g., `BETTER_AUTH_SECRET='a-strong-random-secret-at-least-32-chars'`) or provide it through your hosting environment configuration.
Warnings
- gotcha The module expects a `server/auth.server.config.ts` and `app/auth.client.config.ts` for configuration. These files must be placed in their respective `server/` and `app/` directories for auto-imports and correct module integration.
- breaking Fixes in recent versions (0.1.26, 0.1.25) involved refactoring autoimport registration and separating runtime JS and type declarations for Nitro compatibility. Older setups might experience issues with auto-imports or type resolution.
- gotcha Using `useServerAuth()` requires an `event` object in server routes. For example, `const session = await requireSession(event)`.
- gotcha The `BETTER_AUTH_SECRET` environment variable (or `NUXT_SECRET`) is mandatory for the module to function correctly, ensuring secure session handling.
- gotcha When inferring server auth types from user config, `useServerAuth` might hit TypeScript depth limits if complex session types are used. This was addressed in v0.1.21.
Install
-
npm install nuxt-better-auth-utils -
yarn add nuxt-better-auth-utils -
pnpm add nuxt-better-auth-utils
Imports
- defineNuxtConfig
const defineNuxtConfig = require('nuxt/config')import { defineNuxtConfig } from 'nuxt/config' - useAuth
import { useAuth } from '#nuxt-better-auth-utils'const { session, user, loggedIn } = useAuth() - useServerAuth
import { useServerAuth } from '#nuxt-better-auth-utils'const { requireSession, getSession } = useServerAuth(event) - defineAuthConfig
import { defineAuthConfig } from 'better-auth'import { defineAuthConfig } from '#nuxt-better-auth-utils/server' - defineAuthClientConfig
import { defineAuthClientConfig } from 'better-auth/client'import { defineAuthClientConfig } from '#nuxt-better-auth-utils/client'
Quickstart
import { drizzleAdapter } from 'better-auth/adapters/drizzle';
import { organization } from 'better-auth/plugins';
import { defineDrizzleConfig, useDrizzle } from '#nuxt-drizzle'; // Assuming nuxt-drizzle for DB
// nuxt.config.ts
export default defineNuxtConfig({
modules: [
'nuxt-better-auth-utils',
'#some-database-module' // e.g., 'nuxt-drizzle'
],
betterAuthUtils: {
redirectTo: '/login',
},
// Configure other modules like nuxt-drizzle if used
// drizzle: { ... }
});
// server/auth.server.config.ts
// Ensure database client is available via your preferred Nuxt database module.
// This example assumes `useDrizzle()` from `nuxt-drizzle`.
export default defineAuthConfig(() => {
// In a real application, replace useDrizzle with your actual database client setup
const db = useDrizzle(); // Example using a hypothetical nuxt-drizzle hook
return {
database: drizzleAdapter(db, { provider: 'pg' }), // Replace with your adapter
emailAndPassword: { enabled: true },
plugins: [organization()],
};
});
// app/auth.client.config.ts
import { organizationClient } from 'better-auth/client/plugins';
export default defineAuthClientConfig({
plugins: [organizationClient()],
});
// pages/protected.vue
<script setup lang="ts">
definePageMeta({
middleware: 'auth',
});
const { session, user, loggedIn, signOut } = useAuth();
</script>
<template>
<div>
<h1>Welcome, {{ user?.email }}!</h1>
<p v-if="loggedIn">You are logged in.</p>
<button @click="signOut({ redirectTo: '/login' })">Sign Out</button>
</div>
</template>