X Enterprises

nuxt-x-auth-better

Nuxt 4 authentication layer powered by Better Auth — 7 XAuth-prefixed components, a useXAuth composable, global auth middleware, 6 pre-built pages, and a fully typed app.config.ts interface built on Nuxt UI v4.

nuxt-x-auth-better

Better Auth frontend layer for Nuxt 4. Provides 7 auto-imported XAuth-prefixed components, a useXAuth composable, a global auth middleware, 7 pre-built auth pages, and a fully typed app.config.ts interface — all built on Nuxt UI v4. Pairs with @xenterprises/fastify-x-auth-better on the backend.

Installation

npm install @xenterprises/nuxt-x-auth-better
// nuxt.config.ts
export default defineNuxtConfig({
  extends: [['@xenterprises/nuxt-x-auth-better', { install: true }]],
  runtimeConfig: {
    public: {
      x: {
        auth: {
          baseUrl: process.env.NUXT_PUBLIC_AUTH_BASE_URL || '',
          authPath: '/auth',
        },
      },
    },
  },
})

Override defaults in app.config.ts:

export default defineAppConfig({
  xAuth: {
    redirects: {
      login: '/auth/login',
      signup: '/auth/signup',
      afterLogin: '/',
      afterSignup: '/',
      afterLogout: '/auth/login',
      forgotPassword: '/auth/forgot-password',
    },
    features: {
      oauth: false,
      magicLink: false,
      otp: false,
      forgotPassword: true,
      signup: true,
    },
    oauthProviders: [],
    ui: {
      showLogo: true,
      showBrandName: true,
      brandName: '',
      tagline: '',
      layout: 'centered',
    },
  },
})

What the Layer Provides

Components (auto-imported, XAuth prefix):

  • XAuthLogin — Email/password login form with optional magic link and OAuth
  • XAuthSignup — Registration form with name, email, and password
  • XAuthForgotPassword — Password reset request form
  • XAuthMagicLink — Magic link email input form
  • XAuthOAuthButton — Single OAuth provider button (Google, GitHub, etc.)
  • XAuthOAuthButtonGroup — Multiple OAuth provider buttons from app.config.ts
  • XAuthHandler — Callback handler for OAuth and magic link redirects

Composable:

  • useXAuth() — Full Better Auth client wrapper with session state, auth methods, and user management

Pages:

  • /auth/login — Login page
  • /auth/signup — Signup page
  • /auth/forgot-password — Forgot password page
  • /auth/magic-link — Magic link request page
  • /auth/reset-password — Reset password page (token from email link)
  • /auth/handler/[...slug] — OAuth callback and magic link verification handler
  • /auth/logout — Logout action page

Middleware:

  • auth.global — Global route guard; redirects unauthenticated users to login and authenticated users away from guest-only routes

App Config Options

Configure under the xAuth key in app.config.ts:

OptionTypeDefaultDescription
redirects.loginstring'/auth/login'Login page path
redirects.signupstring'/auth/signup'Signup page path
redirects.afterLoginstring'/'Redirect after successful login
redirects.afterSignupstring'/'Redirect after successful signup
redirects.afterLogoutstring'/auth/login'Redirect after logout
redirects.forgotPasswordstring'/auth/forgot-password'Forgot password page path
features.oauthbooleanfalseShow OAuth provider buttons
features.magicLinkbooleanfalseShow magic link option
features.otpbooleanfalseShow OTP input
features.forgotPasswordbooleantrueShow forgot password link
features.signupbooleantrueShow signup link
oauthProvidersarray[]OAuth providers: { id, label, icon }
ui.showLogobooleantrueShow logo on auth pages
ui.showBrandNamebooleantrueShow brand name on auth pages
ui.brandNamestring''Brand name text
ui.taglinestring''Tagline below brand name
ui.layout'centered' | 'split''centered'Auth page layout
ui.background.enabledbooleantrueShow background on auth pages
ui.background.imageUrlstring''Background image URL
ui.background.overlayOpacitynumber55Overlay opacity (0–100)
ui.background.blurbooleantrueBlur background image
ui.card.glassbooleanfalseGlass morphism card effect
ui.split.heroPosition'left' | 'right''left'Hero panel position in split layout
ui.split.headlinestring''Headline in split layout hero
ui.split.featuresstring[]Feature list in split layout hero
ui.legal.copyrightstring''Copyright text in footer
ui.legal.linksarray[]Footer links: { label, to }

Runtime Config

KeyEnv VariableDefaultDescription
public.x.auth.baseUrlNUXT_PUBLIC_AUTH_BASE_URL''Base URL of the Fastify API server
public.x.auth.authPath'/auth'Better Auth mount path on the API server

The full auth URL is constructed as baseUrl + authPath (e.g. https://api.example.com/auth).

useXAuth() Composable

const {
  user,               // ComputedRef<AuthUser | null>
  isAuthenticated,    // ComputedRef<boolean>
  isLoading,          // ComputedRef<boolean>
  emailSent,          // Ref<boolean>
  session,            // ComputedRef<Session | null>
  sessionError,       // ComputedRef<Error | null>
  config,             // ComputedRef<AuthConfig>
  authClient,         // Better Auth client instance

  login,              // (email, password) => Promise<AuthUser | null>
  signup,             // (email, password, name?) => Promise<AuthUser | null>
  logout,             // () => Promise<boolean>
  forgotPassword,     // (email) => Promise<boolean>
  resetPassword,      // (token, newPassword) => Promise<true | { error }>
  loginWithProvider,  // (providerName) => Promise<boolean>
  sendMagicLink,      // (email, options?) => Promise<boolean>
  getCurrentUser,     // () => Promise<AuthUser | null>
  getToken,           // () => Promise<string | null>
  getAuthHeaders,     // () => Promise<{ Authorization: string }>
  handleMagicLinkCallback, // (token) => Promise<true | { error }>
  changePassword,     // (currentPassword, newPassword) => Promise<true | { error }>
  updateUser,         // ({ name?, image? }) => Promise<true | { error }>
  deleteAccount,      // () => Promise<boolean>
  resetState,         // () => void
} = useXAuth()

Minimal Usage Example

<script setup>
const { user, isAuthenticated, logout } = useXAuth()
</script>

<template>
  <div v-if="isAuthenticated">
    Welcome, {{ user?.name }}
    <UButton @click="logout">Sign Out</UButton>
  </div>
  <XAuthLogin v-else />
</template>

OAuth Providers Example

// app.config.ts
export default defineAppConfig({
  xAuth: {
    features: { oauth: true },
    oauthProviders: [
      { id: 'google', label: 'Google', icon: 'i-simple-icons-google' },
      { id: 'github', label: 'GitHub', icon: 'i-simple-icons-github' },
    ],
  },
})
<XAuthOAuthButtonGroup />

Global Middleware Behavior

The auth.global middleware runs on every route navigation:

Route typeAuthenticatedUnauthenticated
Guest-only (/auth/login, /auth/signup, etc.)Redirect to afterLoginAllow
Public (/auth/handler/*, /auth/logout)AllowAllow
All other routesAllowRedirect to login

Layer Architecture

PathPurpose
nuxt.config.tsRegisters @nuxt/ui, injects runtime config schema
app.config.tsAll configurable options under xAuth namespace with TypeScript type augmentation
app/composables/useXAuth.tsBetter Auth client wrapper — all session state and auth methods
app/components/XAuth/7 auto-imported XAuth-prefixed components
app/pages/auth/7 pre-built auth pages
app/layouts/auth.vueAuth layout (centered card or split panel)
app/middleware/auth.global.tsGlobal route guard
app/plugins/auth-token.tsToken injection plugin
app/utils/cookieStorage, fieldMapper utilities

Environment Variables

VariableRequiredDescription
NUXT_PUBLIC_AUTH_BASE_URLYesBase URL of the Fastify API server (e.g. https://api.example.com)
Copyright © 2026