nuxt-x-auth-stack
Nuxt 4 authentication layer powered by Stack Auth — 10 XAuth-prefixed components, a useXAuth composable with OAuth/magic-link/OTP/password-reset support, global auth middleware, and 8 pre-built pages built on Nuxt UI v4.
nuxt-x-auth-stack
Stack Auth (stack-auth.com) frontend layer for Nuxt 4. Provides 10 auto-imported XAuth-prefixed components, a useXAuth composable, a global auth middleware, and 7 pre-built auth pages — all built on Nuxt UI v4. Client-side only (ssr: false).
Installation
npm install @xenterprises/nuxt-x-auth-stack
// nuxt.config.ts
export default defineNuxtConfig({
extends: [['@xenterprises/nuxt-x-auth-stack', { install: true }]],
runtimeConfig: {
public: {
stack: {
projectId: process.env.NUXT_PUBLIC_STACK_PROJECT_ID,
publishableClientKey: process.env.NUXT_PUBLIC_STACK_PUBLISHABLE_CLIENT_KEY,
},
},
},
})
What the Layer Provides
Components (auto-imported, XAuth prefix):
XAuthLogin— Email/password login form with optional magic link and OAuth buttonsXAuthSignup— Registration form with email, password, and optional nameXAuthForgotPassword— Password reset request formXAuthMagicLink— Magic link email input formXAuthMagicLinkCallback— Magic link callback handler componentXAuthOtp— OTP (email code) input and verification formXAuthOAuthButton— Single OAuth provider buttonXAuthOAuthButtonGroup— Multiple OAuth provider buttons fromapp.config.tsXAuthHandler— Handler component for all auth callbacks (OAuth, magic link, email verification, password reset)XAuthForm— Base form wrapper used by auth page components
Composable:
useXAuth()— Stack Auth client wrapper with SSR-safe shared state and all auth methods
Pages:
/auth/login— Login page/auth/signup— Signup page/auth/forgot-password— Forgot password page/auth/magic-link— Magic link request page/auth/otp— OTP verification page/auth/handler/[...slug]— Catch-all callback handler (OAuth, magic link, email verification, password reset)/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
// 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: [],
},
})
useXAuth() Composable
SSR-safe via Nuxt useState — shared state across all composable instances on the same page.
const {
user, // Ref<XAuthUser | null>
isAuthenticated, // ComputedRef<boolean>
isLoading, // Ref<boolean>
emailSent, // Ref<boolean>
codeSent, // Ref<boolean>
config, // ComputedRef<XAuthConfig>
login, // (email, password) => Promise<XAuthUser | null>
signup, // (email, password) => Promise<XAuthUser | null>
logout, // () => Promise<boolean>
loginWithProvider, // (providerName) => Promise<boolean>
forgotPassword, // (email) => Promise<boolean>
resetPassword, // (code, newPassword) => Promise<{ success } | { error }>
verifyPasswordResetCode,// (code) => Promise<result>
sendMagicLink, // (email) => Promise<boolean>
signInWithMagicLink, // (code) => Promise<{ success } | { error }>
sendOtp, // (email) => Promise<string | null> — returns nonce
verifyOtp, // (code, nonce) => Promise<XAuthUser | null>
verifyEmail, // (code) => Promise<{ success } | { error }>
getCurrentUser, // () => Promise<XAuthUser | null>
getToken, // () => Promise<string | null>
getAuthHeaders, // () => Promise<{ Authorization: string }>
resetState, // () => void
getClient, // () => StackClientApp
} = useXAuth()
XAuthUser Type
interface XAuthUser {
id: string
email: string
name: string
avatar?: string
emailVerified: boolean
metadata: Record<string, any>
}
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
| Route type | Authenticated | Unauthenticated |
|---|---|---|
Guest-only (/auth/login, /auth/signup, etc.) | Redirect to afterLogin | Allow |
Public (/auth/handler/*, /auth/logout) | Allow | Allow |
| All other routes | Allow | Redirect to login |
Layer Architecture
| Path | Purpose |
|---|---|
nuxt.config.ts | Registers @nuxt/ui, @nuxt/fonts; sets ssr: false; injects runtime config schema |
app.config.ts | All configurable options under xAuth namespace |
app/composables/useXAuth.ts | Stack Auth client singleton wrapper — all session state and auth methods |
app/components/XAuth/ | 10 auto-imported XAuth-prefixed components |
app/pages/auth/ | 7 pre-built auth pages |
app/layouts/auth.vue | Auth layout (centered card) |
app/middleware/auth.global.ts | Global route guard |
app/plugins/auth-init.client.ts | Client-side Stack Auth initialization plugin |
Environment Variables
| Variable | Required | Description |
|---|---|---|
NUXT_PUBLIC_STACK_PROJECT_ID | Yes | Stack Auth project ID |
NUXT_PUBLIC_STACK_PUBLISHABLE_CLIENT_KEY | Yes | Stack Auth publishable client key |
