nuxt-x-neon-auth
nuxt-x-neon-auth
Authentication layer for Nuxt 4 using Neon Auth (Better Auth). Provides pre-built auth pages, 10 components, two composables (useXAuth and useXNeonAuth), and a global route middleware. Supports email/password, OAuth, OTP, and magic links.
Installation
npm install @xenterprises/nuxt-x-neon-auth
// nuxt.config.ts
export default defineNuxtConfig({
extends: ["@xenterprises/nuxt-x-neon-auth"],
});
// app.config.ts
export default defineAppConfig({
xAuth: {
redirects: {
login: "/auth/login",
afterLogin: "/",
afterLogout: "/auth/login",
},
features: {
oauth: false,
magicLink: false,
otp: false,
forgotPassword: true,
},
socialLoginProviders: ["google", "github"],
},
});
What This Layer Provides
- Components — XAuthLogin, XAuthSignup, XAuthForgotPassword, XAuthMagicLink, XAuthOtp, XAuthMagicLinkCallback, XAuthOAuthButton, XAuthOAuthButtonGroup, XAuthErrorBoundary, XAuthHandler
- Composables — useXAuth (high-level), useXNeonAuth (low-level)
- Pages — auto-registered:
/auth/login,/auth/signup,/auth/forgot-password,/auth/magic-link,/auth/otp,/auth/logout,/auth/handler/[slug] - Global middleware — automatic route protection
Configuration (app.config.ts)
| Option | Type | Default | Description |
|---|---|---|---|
redirects.login | string | "/auth/login" | Login page path. |
redirects.signup | string | "/auth/signup" | Signup page path. |
redirects.afterLogin | string | "/" | Redirect after login. |
redirects.afterSignup | string | "/" | Redirect after signup. |
redirects.afterLogout | string | "/auth/login" | Redirect after logout. |
features.oauth | boolean | false | Enable OAuth/social login. |
features.magicLink | boolean | false | Enable magic link auth. |
features.otp | boolean | false | Enable OTP auth. |
features.forgotPassword | boolean | true | Enable password reset. |
socialLoginProviders | OAuthProvider[] | ["google"] | OAuth providers to display. |
useXAuth() Composable
High-level composable with toast notifications, loading states, and automatic navigation.
| Property / Method | Type | Description |
|---|---|---|
user | () => Promise<User | null> | Get current user. |
isLoading | Ref<boolean> | Loading state. |
isAuthenticated | Ref<boolean> | Auth status (call checkAuth() first). |
emailSent | Ref<boolean> | Whether an email was sent (magic link / forgot password). |
codeSent | Ref<boolean> | Whether an OTP code was sent. |
checkAuth() | Promise<User | null> | Check auth status and update isAuthenticated. |
login(email, password) | Promise<User | null> | Sign in with credentials. |
signup(email, password) | Promise<User | null> | Create account. |
logout() | Promise<boolean> | Sign out. |
forgotPassword(email) | Promise<boolean> | Send password reset email. |
resetPassword(code, password) | Promise<true | {error}> | Reset password with token. |
loginWithProvider(provider) | Promise<boolean> | OAuth sign in. |
sendOtp(email) | Promise<boolean> | Send OTP code. |
verifyOtp(code) | Promise<User | null> | Verify OTP code. |
sendMagicLink(email) | Promise<boolean> | Send magic link email. |
handleMagicLinkCallback(token) | Promise<true | {error}> | Verify magic link token. |
changePassword(current, new) | Promise<boolean> | Change password (authenticated). |
updateUser({name?, image?}) | Promise<boolean> | Update user profile. |
deleteAccount(password) | Promise<boolean> | Delete user account. |
resetState() | void | Reset emailSent and codeSent. |
authClient | object | Direct access to Neon Auth client. |
useXNeonAuth() Composable
Lower-level composable wrapping the Neon Auth client with Vue reactivity. Returns { status: "ok", data? } or { status: "error", error: { message } }.
| Method | Description |
|---|---|
currentUser() | Get current session user. |
signInWithCredential(email, password) | Sign in with email/password. |
signUpWithCredential(email, password, name?) | Create account. |
signOut() | Sign out. |
signInWithOAuth(provider, options?) | OAuth sign in. |
sendOtpCode(email) | Send OTP verification code. |
verifyOtpCode(otp) | Verify OTP code. |
sendMagicLinkEmail(email, options?) | Send magic link. |
verifyMagicLink(token) | Verify magic link token. |
sendForgotPasswordEmail(email) | Send password reset email. |
changePassword(current, new) | Change password. |
updateUser({name?, image?}) | Update profile. |
deleteAccount(password) | Delete account. |
authClient | Raw Neon Auth client. |
Components
| Component | Description |
|---|---|
XAuthLogin | Login form with email/password, OAuth, OTP/magic link links. |
XAuthSignup | Signup form with email/password and OAuth. |
XAuthForgotPassword | Password reset request form. |
XAuthMagicLink | Magic link email form. |
XAuthOtp | OTP email + code verification form. |
XAuthMagicLinkCallback | Magic link token verification handler. |
XAuthOAuthButton | Single OAuth provider button with inline SVG icons. |
XAuthOAuthButtonGroup | Group of OAuth buttons from config. |
XAuthErrorBoundary | Error display with optional retry. |
XAuthHandler | Generic auth callback handler (magic-link, password-reset, oauth, email-verification). |
XAuthHandler Props
| Prop | Type | Default | Description |
|---|---|---|---|
type | "magic-link" | "password-reset" | "oauth" | "email-verification" | required | Handler type. |
redirectTo | string | "/" | Redirect after success. |
redirectDelay | number | 1500 | Delay before redirect (ms). |
Auto-Registered Pages
| Path | Description |
|---|---|
/auth/login | Login page. |
/auth/signup | Signup page. |
/auth/forgot-password | Password reset request. |
/auth/magic-link | Magic link sign in. |
/auth/otp | OTP sign in. |
/auth/logout | Logout page. |
/auth/handler/[slug] | Auth callback handler. |
Route Protection
The global middleware runs on every navigation:
- Redirects authenticated users away from
/auth/*to home. - Redirects unauthenticated users from protected pages to
/auth/login. - Allows unauthenticated access to
/handler/*callback routes.
Environment Variables
| Variable | Required | Description |
|---|---|---|
NUXT_PUBLIC_NEON_AUTH_URL | Yes | Neon Auth endpoint URL (e.g. https://your-project.neonauth.xxx.neon.tech/your-db/auth). |
Supported OAuth Providers
Google, GitHub, Apple, Microsoft, Discord, Facebook, Twitter, LinkedIn, GitLab, Spotify, Twitch, Slack, Notion, Linear, Figma, Atlassian, Salesforce, Cognito, and 30+ more via Better Auth.
Error Reference
useXAuth() methods show toast notifications on error. useXNeonAuth() returns structured errors:
| Error | Context |
|---|---|
"No OTP session found" | verifyOtpCode called without sending a code first. |
"Invalid credentials" | Wrong email or password. |
"Email already exists" | Account already registered. |
"Token expired" | Auth token expired (magic link or password reset). |
"Incorrect password" | Current password wrong in changePassword. |
How It Works
useXNeonAuth() creates a client via createAuthClient() from @neondatabase/neon-js/auth, pointing to your Neon Auth endpoint. useXAuth() wraps it with loading states, toast notifications (Nuxt UI), and automatic navigation after auth events. The global middleware checks session status via currentUser() on every route change. Pre-built pages render the matching component using the auth layout (centered card on gray background). Components are built with Nuxt UI v4 and use Zod for form validation.
