@xenterprises/nuxt-x-auth-stack
v0.2.1
Published
Stack Auth authentication layer for Nuxt with OAuth, OTP, and Magic Link support
Readme
@xenterprises/nuxt-x-auth-stack
Stack Auth authentication layer for Nuxt with OAuth, OTP, Magic Link, and email/password support. Features a glassmorphism video-background login experience, automatic route protection, and full customization via app.config.ts.
Install
npm install @xenterprises/nuxt-x-auth-stackQuick Start
- Extend the layer in your
nuxt.config.ts:
export default defineNuxtConfig({
extends: ['@xenterprises/nuxt-x-auth-stack'],
})- Add environment variables to
.env:
NUXT_PUBLIC_STACK_PROJECT_ID=your-project-id
NUXT_PUBLIC_STACK_PUBLISHABLE_CLIENT_KEY=your-publishable-key- Configure features in
app.config.ts:
export default defineAppConfig({
xAuth: {
features: {
signup: true,
oauth: true,
forgotPassword: true,
},
oauthProviders: [
{ id: 'google', label: 'Continue with Google', icon: 'i-simple-icons-google' },
],
redirects: {
afterLogin: '/dashboard',
},
},
})Configuration
Options (app.config.ts -> xAuth)
| 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 |
| redirects.forgotPassword | string | "/auth/forgot-password" | Forgot password path |
| publicRoutes | string[] | [] | Extra public routes (no auth required) |
| features.oauth | boolean | false | Enable OAuth providers |
| features.magicLink | boolean | false | Enable Magic Link authentication |
| features.otp | boolean | false | Enable OTP (one-time password) authentication |
| features.forgotPassword | boolean | true | Enable forgot password flow |
| features.signup | boolean | false | Enable user registration |
| legal.termsUrl | string | "/terms" | Terms of Service URL |
| legal.privacyUrl | string | "/privacy" | Privacy Policy URL |
| oauthProviders | Array<{id, label, icon}> | [] | OAuth provider config (google, github, microsoft, facebook, twitter, apple, linkedin, discord, spotify) |
UI Customization (app.config.ts -> xAuth.ui)
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| showLogo | boolean | true | Show logo above auth forms |
| logoUrl | string | X Enterprises logo | Logo image URL |
| brandName | string | "" | Brand name text |
| tagline | string | "" | Brand tagline |
| layout | "centered" \| "split" | "centered" | Auth page layout variant |
| background.type | "gradient" \| "image" \| "video" \| "solid" | "video" | Background type |
| background.videoUrl | string | Mixkit drone footage | Video background URL |
| background.imageUrl | string | "" | Image background URL |
| background.videoCredit | string | "Mixkit" | Video credit text |
| background.videoCreditUrl | string | "https://mixkit.co" | Video credit link |
| background.overlayOpacity | number | 50 | Overlay opacity (0-100) |
| card.glass | boolean | true | Enable glassmorphism |
| card.glassIntensity | "subtle" \| "medium" \| "strong" | "medium" | Glass blur intensity |
| card.opacity | number | 40 | Card background opacity |
| form.icon | string | "" | Icon above form title |
| form.showSeparator | boolean | true | Show "or" separator between OAuth and form |
Composable: useXAuth()
Auto-imported. Returns reactive state and authentication methods.
State
| Property | Type | Description |
|----------|------|-------------|
| user | Ref<XAuthUser \| null> | Current authenticated user |
| isLoading | Ref<boolean> | Loading state for any auth operation |
| isAuthenticated | ComputedRef<boolean> | Whether a user is logged in |
| emailSent | Ref<boolean> | Whether a magic link/reset email was sent |
| codeSent | Ref<boolean> | Whether an OTP code was sent |
| config | ComputedRef<XAuthConfig> | Current auth configuration |
Methods
| Method | Signature | Description |
|--------|-----------|-------------|
| login | (email, password) => Promise<XAuthUser \| null> | Email/password sign in |
| signup | (email, password) => Promise<XAuthUser \| null> | Create account |
| logout | () => Promise<boolean> | Sign out and redirect |
| loginWithProvider | (providerName) => Promise<boolean> | OAuth sign in (redirects) |
| forgotPassword | (email) => Promise<boolean> | Send password reset email |
| resetPassword | (code, newPassword) => Promise<{success?, error?}> | Reset password with code |
| verifyPasswordResetCode | (code) => Promise<any> | Verify reset code validity |
| sendMagicLink | (email) => Promise<boolean> | Send magic link email |
| signInWithMagicLink | (code) => Promise<{success?, error?}> | Complete magic link sign in |
| sendOtp | (email) => Promise<string \| null> | Send OTP code (returns nonce) |
| verifyOtp | (code, nonce) => Promise<XAuthUser \| null> | Verify OTP code |
| verifyEmail | (code) => Promise<{success?, error?}> | Verify email address |
| getCurrentUser | () => Promise<XAuthUser \| null> | Fetch and cache current user |
| getToken | () => Promise<string \| null> | Get JWT access token |
| getAuthHeaders | () => Promise<Record<string, string>> | Get auth headers for API calls |
| resetState | () => void | Reset emailSent/codeSent flags |
| getClient | () => StackClientApp | Get raw Stack client for advanced usage |
XAuthUser Type
interface XAuthUser {
id: string
email: string
name: string
avatar?: string
emailVerified: boolean
metadata?: Record<string, any>
}Components
All components are auto-imported with the XAuth prefix.
| Component | Description |
|-----------|-------------|
| XAuthLogin | Email/password login form with OAuth, OTP, and Magic Link links |
| XAuthSignup | Registration form with terms checkbox and OAuth |
| XAuthForgotPassword | Password reset request with success state |
| XAuthMagicLink | Magic link email form with success state |
| XAuthOtp | Two-step OTP flow: email input then code verification |
| XAuthHandler | Callback handler for OAuth, magic link, password reset, email verification |
| XAuthForm | Reusable form component with field rendering, validation, and slots |
| XAuthOAuthButton | Single OAuth provider button with inline SVG logos |
| XAuthOAuthButtonGroup | Renders multiple OAuth buttons from config |
| XAuthMagicLinkCallback | Wrapper for magic link verification |
XAuthForm Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| icon | string | — | Icon name above title |
| title | string | — | Form title |
| description | string | — | Form description text |
| fields | Array<{name, type, label, placeholder, required}> | [] | Form fields config |
| providers | Array<{label, icon, onClick}> | — | OAuth provider buttons |
| separator | string | — | Text between providers and form |
| submit | {label: string} | {label: 'Continue'} | Submit button config |
| schema | ZodObject | — | Zod validation schema |
| loading | boolean | false | Loading state |
XAuthForm Slots
| Slot | Description |
|------|-------------|
| description | Custom description content |
| password-hint | Content next to password label (e.g. forgot link) |
| leading | Content above the form fields |
| submit | Replace the default submit button |
| footer | Content below the form |
XAuthHandler Props
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| type | "magic-link-callback" \| "oauth-callback" \| "password-reset" \| "email-verification" | Yes | Handler type |
| redirectTo | string | No | Override redirect destination |
| redirectDelay | number | No (1500) | Delay before redirect in ms |
Pages
| Route | Layout | Description |
|-------|--------|-------------|
| /auth/login | auth | Login page |
| /auth/signup | auth | Registration page |
| /auth/forgot-password | auth | Password reset request |
| /auth/magic-link | auth | Magic link email form |
| /auth/otp | auth | OTP authentication |
| /auth/logout | auth | Logout handler |
| /auth/handler/[...slug] | auth | Callback handler (OAuth, magic link, password reset, email verification) |
Route Protection
The layer includes a global middleware that classifies routes:
- Public routes:
/auth/handler/**,/auth/logout,/terms,/privacy+ any routes inpublicRoutesconfig - Guest-only routes:
/auth/login,/auth/signup,/auth/forgot-password,/auth/magic-link,/auth/otp,/auth/reset-password-- authenticated users are redirected toafterLogin - Protected routes: Everything else requires authentication -- unauthenticated users are redirected to
login
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 |
Error Reference
| Error | Context | Description |
|-------|---------|-------------|
| Missing Stack Auth configuration | Startup | NUXT_PUBLIC_STACK_PROJECT_ID or NUXT_PUBLIC_STACK_PUBLISHABLE_CLIENT_KEY not set |
| Sign In Failed | login() | Invalid credentials or network error |
| Sign Up Failed | signup() | Email already exists or validation error |
| Logout Failed | logout() | Error during sign out |
| {provider} Login Failed | loginWithProvider() | OAuth flow error |
| Password Reset Failed | forgotPassword() | Email validation failed |
| Magic Link Failed | sendMagicLink() | Send failure or rate limit |
| OTP Failed | sendOtp() | Code send failure |
| Verification Failed | verifyOtp() | Invalid or expired OTP code |
How It Works
The layer wraps the @stackframe/js SDK (Stack Auth's client library) in a Nuxt-idiomatic composable pattern:
Auth Init Plugin (
auth-init.client.ts): On client load, checks for an existing session via cookies and populates user state.useXAuth Composable: Creates a singleton
StackClientAppinstance configured fromruntimeConfig.public.stack. All auth state (user,isLoading,emailSent,codeSent) uses Nuxt'suseStatefor SSR safety. Methods wrap SDK calls with toast notifications and automatic redirects.Global Middleware (
auth.global.ts): Runs on every route change. Classifies routes as public, guest-only, or protected. CallsgetCurrentUser()to check auth state and redirects accordingly.Handler Component: The catch-all
/auth/handler/[...slug]route delegates toXAuthHandlerwhich handles OAuth callbacks (with polling for user), magic link verification, password reset (with form), and email verification.User Normalization: Raw Stack Auth user objects are normalized to the
XAuthUserinterface using field mapping with fallback chains, so consumers get a consistent shape regardless of Stack Auth API changes.
Layer Architecture
nuxt.config.ts: Registers@nuxt/uiand@nuxt/fontsmodules, configures runtime config for Stack Auth credentials, pre-bundles CJS dependencies.app.config.ts: Defines all configurable options (redirects, features, OAuth providers, UI customization). Consumer apps override via their ownapp.config.ts.app/: Contains all components, composables, middleware, plugins, pages, and layouts.types/: TypeScript interfaces forXAuthUser,XAuthResult, andXAuthConfig.
Requirements
- Nuxt >= 4.0.0
- @nuxt/ui >= 4.0.0
- Node.js >= 18.0.0
- A Stack Auth project (stackauth.com)
