BETTER-STACK

Better Auth UI Plugin (Beta)

Beautiful shadcn/ui authentication components for better-auth

Better Auth UI Demo

The Better Auth UI plugin provides beautiful, plug-and-play authentication UI components built with shadcn/ui for better-auth. This is a fork of the popular better-auth-ui library, adapted for seamless integration with Better Stack.

Features

  • Sign In / Sign Up – Complete authentication flows with email, password, social login, and magic links
  • Account Management – User profile settings, password changes, and account deletion
  • Two-Factor Authentication – TOTP and OTP support for enhanced security
  • Social Login – GitHub, Google, Discord, and more OAuth providers
  • Passkeys – WebAuthn/Passkey authentication support
  • Organizations – Team and organization management with invitations and roles
  • Fully Customizable – Built with TailwindCSS and shadcn/ui for easy styling

Installation

Before starting, ensure you have:

  • A Next.js project with @btst/stack already set up (see Installation)
  • better-auth configured (server-side auth)
  • A better-auth client (lib/auth-client.ts) set up
  • A database adapter (e.g., Drizzle with @btst/adapter-drizzle)

1. Install the Package

pnpm add @btst/better-auth-ui

Or with npm/yarn:

npm install @btst/better-auth-ui
# or
yarn add @btst/better-auth-ui

2. Configure the Stack Client (Server-Side)

Import and register the auth plugins in your better-stack-client.tsx file:

lib/better-stack-client.tsx
import { createStackClient } from "@btst/stack/client"
import { 
  authClientPlugin, 
  accountClientPlugin, 
  organizationClientPlugin 
} from "@btst/better-auth-ui/client"
import { QueryClient } from "@tanstack/react-query"

const getBaseURL = () => 
  process.env.BASE_URL || "http://localhost:3000"

export function getStackClient(queryClient: QueryClient, options?: { headers?: Headers }) {
  const baseURL = getBaseURL()

  return createStackClient({
    plugins: {
      // Auth plugin - handles sign-in, sign-up, forgot-password, etc.
      auth: authClientPlugin({
        siteBaseURL: baseURL,
        siteBasePath: "/p",  // Your base path for routes
      }),
      
      // Account plugin - handles settings, profile management
      account: accountClientPlugin({
        siteBaseURL: baseURL,
        siteBasePath: "/p",
      }),
      
      // Organization plugin - handles team/org management
      organization: organizationClientPlugin({
        siteBaseURL: baseURL,
        siteBasePath: "/p",
      }),
      
      // ... other plugins (blog, cms, etc.)
    },
  })
}

3. Configure the BetterStackProvider (Client-Side Layout)

Configure the plugin overrides in your catch-all layout file:

app/p/[[...all]]/layout.tsx
"use client"

import { BetterStackProvider } from "@btst/stack/context"
import type { 
  AuthPluginOverrides, 
  AccountPluginOverrides,
  OrganizationPluginOverrides 
} from "@btst/better-auth-ui/client"
import { authClient } from "@/lib/auth-client"
import Link from "next/link"
import { useRouter } from "next/navigation"
import type { ReactNode } from "react"

type PluginOverrides = {
  auth: AuthPluginOverrides
  account: AccountPluginOverrides
  organization: OrganizationPluginOverrides
}

export default function PagesLayout({ children }: { children: ReactNode }) {
  const router = useRouter()

  // Shared auth configuration
  const authConfig = {
    authClient: authClient,              // Your better-auth client
    navigate: router.push,               // Navigation function
    replace: router.replace,             // Replace navigation
    onSessionChange: () => router.refresh(), // Refresh on session change
    Link: Link,                          // Next.js Link component
  }

  return (
    <BetterStackProvider<PluginOverrides>
      basePath="/p"
      overrides={{
        auth: {
          ...authConfig,
          basePath: "/p/auth",           // Auth routes base path
          redirectTo: "/p/account/settings", // Where to redirect after login
          // Optional features:
          // social: { providers: ["github", "google"] },
          // magicLink: true,
          // passkey: true,
          // twoFactor: ["otp", "totp"],
        },
        account: {
          ...authConfig,
          basePath: "/p/account",        // Account routes base path
          account: {
            fields: ["image", "name"],   // Editable profile fields
          },
          // Optional: Enable avatar upload
          // avatar: {
          //   upload: async (file) => {
          //     const blob = await uploadImage(file);
          //     return blob.url;
          //   },
          //   size: 128,
          //   extension: "png",
          // },
          // Optional: Allow account deletion
          // deleteUser: true,
        },
        organization: {
          ...authConfig,
          basePath: "/p/org",            // Organization routes base path
        },
      }}
    >
      {children}
    </BetterStackProvider>
  )
}

4. Import Required CSS

Add the better-auth-ui styles to your global stylesheet:

app/globals.css
@import "@btst/better-auth-ui/css";

Available Routes

Once configured, the following routes become available:

Auth Routes

RouteDescription
/p/auth/sign-inSign in page
/p/auth/sign-upSign up page
/p/auth/forgot-passwordPassword reset request
/p/auth/reset-passwordPassword reset form
/p/auth/callbackOAuth callback handler

Account Routes

RouteDescription
/p/account/settingsUser settings page
/p/account/securitySecurity settings (password, 2FA)

Organization Routes

RouteDescription
/p/orgOrganization dashboard
/p/org/createCreate new organization
/p/org/settingsOrganization settings
/p/org/membersTeam member management
/p/org/invitationsPending invitations

Routes are prefixed with your configured basePath. The examples above use /p as the base path.

Configuration Options

Social Login

Enable social login providers:

auth: {
  ...authConfig,
  social: { 
    providers: ["github", "google", "discord"] 
  },
}

Enable passwordless authentication via email:

auth: {
  ...authConfig,
  magicLink: true,
}

Two-Factor Authentication

Enable 2FA with OTP or TOTP:

auth: {
  ...authConfig,
  twoFactor: ["otp", "totp"],
}

Passkeys

Enable WebAuthn/Passkey authentication:

auth: {
  ...authConfig,
  passkey: true,
}

Avatar Upload

Enable avatar upload in account settings:

account: {
  ...authConfig,
  avatar: {
    upload: async (file) => {
      // Your upload logic - return the URL
      const blob = await uploadImage(file);
      return blob.url;
    },
    size: 128,
    extension: "png",
  },
}

Account Deletion

Allow users to delete their accounts:

account: {
  ...authConfig,
  deleteUser: true,
}

Organizations

Enable team and organization management:

lib/better-stack-client.tsx
import { organizationClientPlugin } from "@btst/better-auth-ui/client"

// In your plugins config:
organization: organizationClientPlugin({
  siteBaseURL: baseURL,
  siteBasePath: "/p",
  context: {
    // Optional: Pass additional context to organization routes
  },
}),

Configure organization overrides in the provider:

organization: {
  ...authConfig,
  basePath: "/p/org",
  // Organization-specific options
  logo: true, // Enable organization logo upload
  customRoles: [
    { role: "editor", label: "Editor" },
    { role: "viewer", label: "Viewer" },
  ],
  apiKey: false, // Enable API key support for organizations
  pathMode: "default", // or "slug" for slug-based URLs
  // slug: "my-org", // Current organization slug (when using pathMode: "slug")
  // personalPath: "/dashboard", // Redirect path when Personal Account is selected
}

Learn More

For comprehensive documentation on all configuration options, customization, and advanced features, visit: