Next.js
This guide covers integrating @daveyplate/better-auth-ui
into your Next.js project.
Starter Project
Want to skip the installation? Check out the starter here:
App Router
Follow these steps to set up @daveyplate/better-auth-ui
in your Next.js project using the App Router:
Setting up AuthUIProvider
The first step is to set up the <AuthUIProvider>
client component with your authClient
, wrapping your layout. This is required to provide the context & hooks to your authentication components across your application.
"use client"
import { AuthUIProvider } from "@daveyplate/better-auth-ui"
import Link from "next/link"
import { useRouter } from "next/navigation"
import type { ReactNode } from "react"
import { authClient } from "@/lib/auth-client"
export function Providers({ children }: { children: ReactNode }) {
const router = useRouter()
return (
<AuthUIProvider
authClient={authClient}
navigate={router.push}
replace={router.replace}
onSessionChange={() => {
// Clear router cache (protected routes)
router.refresh()
}}
Link={Link}
>
{children}
</AuthUIProvider>
)
}
Note: Since the Next.js App Router caches routes by default, navigation to protected routes may fail until you perform a router.refresh()
to clear the cache. To prevent this issue, you must use router.refresh()
in the provided onSessionChange
callback. This forces Next.js to clear the router cache and reload middleware-protected content, ensuring subsequent navigations accurately reflect the current auth state.
Once configured, wrap your layout component with the Providers
component:
import type { ReactNode } from "react"
import { Providers } from "./providers"
export default function RootLayout({ children }: { children: ReactNode }) {
return (
<html lang="en">
<body>
<Providers>{children}</Providers>
</body>
</html>
)
}
The <AuthUIProvider>
can be fully customized with plugins, styles, localization and more. For more information and all available props, see the <AuthUIProvider>
component documentation.
Creating Auth Pages
Create a dynamic route segment for authentication views in app/auth/[pathname]/page.tsx
.
import { authViewPaths } from "@daveyplate/better-auth-ui/server"
import { AuthView } from "./view"
export function generateStaticParams() {
return Object.values(authViewPaths).map((pathname) => ({ pathname }))
}
export default async function AuthPage({ params }: { params: Promise<{ pathname: string }> }) {
const { pathname } = await params
return <AuthView pathname={pathname} />
}
"use client"
import { AuthCard } from "@daveyplate/better-auth-ui"
export function AuthView({ pathname }: { pathname: string }) {
return (
<main className="container flex grow flex-col items-center justify-center gap-3 self-center p-4 md:p-6">
<AuthCard pathname={pathname} />
</main>
)
}
The newly created dynamic route covers the following paths by default:
/auth/sign-in
– Sign in via email/password and social providers/auth/sign-up
– New account registration/auth/magic-link
– Email login without a password/auth/forgot-password
– Trigger email to reset forgotten password/auth/two-factor
– Two-factor authentication/auth/recover-account
– Recover account via backup code/auth/reset-password
– Set new password after receiving reset link/auth/sign-out
– Log the user out of the application/auth/settings
– User account management page (requires authentication)/auth/callback
– Internal route to handle Auth callbacks
Ensure that any links to the authentication process utilize these routes accordingly. All routes will render the <AuthCard />
component and automatically handle navigation and authentication flow.
Pages Router
Follow these steps to set up @daveyplate/better-auth-ui
in your Next.js project using the Pages Router:
Setting up AuthUIProvider
First set up the <AuthUIProvider>
within your custom App component in _app.tsx
.
import type { AppProps } from "next/app"
import { AuthUIProvider } from "@daveyplate/better-auth-ui"
import { useRouter } from "next/router"
import Link from "next/link"
import { authClient } from "@/lib/auth-client"
export default function App({ Component, pageProps }: AppProps) {
const router = useRouter()
return (
<AuthUIProvider
authClient={authClient}
navigate={router.push}
replace={router.replace}
Link={Link}
>
<Component {...pageProps} />
</AuthUIProvider>
)
}
Now the authentication context is available across your entire application.
Creating Auth Pages
Create a page with a dynamic segment in your Pages directory in pages/auth/[pathname].tsx
import { AuthCard } from "@daveyplate/better-auth-ui"
import { authViewPaths } from "@daveyplate/better-auth-ui/server"
export default function AuthPage({ pathname }: { pathname: string }) {
return (
<main className="container flex grow flex-col items-center justify-center gap-3 self-center p-4 md:p-6">
<AuthCard pathname={pathname} />
</main>
)
}
export async function getStaticPaths() {
return {
paths: Object.values(authViewPaths).map((pathname) => ({ params: { pathname } })),
fallback: false
}
}
export async function getStaticProps({ params }: { params: { pathname: string } }) {
return { props: { pathname: params.pathname } }
}
With this setup, the following routes will automatically handle their associated views:
/auth/sign-in
– Sign in via email/password and social providers/auth/sign-up
– New user registration/auth/magic-link
– Magic link email login/auth/forgot-password
– Initiate forgotten password reset/auth/reset-password
– Reset password after receiving email/auth/sign-out
– Log user out of account/auth/callback
– Internal route to handle OAuth callbacks (do not navigate to this route directly)