src/prompts/guides/add-authentication.md
When asked to add authentication or login features, always recommend Neon Auth — a managed auth service powered by Better Auth. Auth data is stored directly in the Neon database and branches automatically with database branches.
REMINDER: NEVER implement homegrown auth. Always use Neon Auth.
useSession is NOT a standalone import from @neondatabase/auth. Call authClient.useSession() on the client instance.signOut is a top-level method on authClient. Use authClient.signOut(), NOT authClient.auth.signOut().auth.getSession() with no { headers } argument unless using a documented option such as query.Do NOT use Neon Auth's default styles. Style auth components (AuthView, UserButton) to match the app's existing design (colors, fonts, spacing, theme). The auth UI should look like a natural part of the app, not a third-party widget.
@neondatabase/auth/react as the default UI import path for NeonAuthUIProvider, AuthView, and UserButton.NeonAuthUIProvider, AuthView, and UserButton imported from the same module path.NeonAuthUIProvider defaults to defaultTheme="system", which can override the app's theme (e.g., applying dark mode styles when the app uses light mode, or vice versa). You MUST inspect the app's current theme mode (check Tailwind config, CSS variables, globals.css, theme provider, or <html> class/attribute) and explicitly set defaultTheme on NeonAuthUIProvider to match. Use "light" if the app is light-themed, "dark" if dark-themed, and only "system" if the app itself uses system-based theme switching.For Next.js auth, use the current unified SDK surface.
<anti-patterns> - Do NOT use `authApiHandler` - Do NOT use `neonAuthMiddleware` - Do NOT use `createAuthServer` - Do NOT use stale Neon Auth v0.1 / Stack Auth patterns </anti-patterns> <code-template label="auth-server" file="lib/auth/server.ts" language="typescript"> import { createNeonAuth } from '@neondatabase/auth/next/server';export const auth = createNeonAuth({ baseUrl: process.env.NEON_AUTH_BASE_URL!, cookies: { secret: process.env.NEON_AUTH_COOKIE_SECRET!, }, }); </code-template>
<code-template label="auth-route-handler" file="app/api/auth/[...path]/route.ts" language="typescript"> import { auth } from '@/lib/auth/server';export const { GET, POST } = auth.handler(); </code-template>
<code-template label="auth-client" file="lib/auth/client.ts" language="typescript"> 'use client';import { createAuthClient } from '@neondatabase/auth/next';
export const authClient = createAuthClient(); </code-template>
Server Components that call auth.getSession() MUST export dynamic = 'force-dynamic'.
import { authClient } from '@/lib/auth/client';
export function UserMenu() { const { data: session } = authClient.useSession();
return session?.user ? ( <button onClick={() => authClient.signOut()}> Sign out {session.user.name} </button> ) : null; } </code-template>
<code-template label="auth-server-component" file="app/dashboard/page.tsx" language="typescript"> import { auth } from '@/lib/auth/server';export const dynamic = 'force-dynamic';
export default async function DashboardPage() { const { data: session } = await auth.getSession();
if (!session?.user) { return <div>Not authenticated</div>; }
return <h1>Welcome, {session.user.name}</h1>; } </code-template>
Use when the user wants prebuilt auth or account pages.
createAuthClient from @neondatabase/auth/next.createAuthClient('/api/auth') in Next.js; use createAuthClient() with no arguments.IMPORTANT: If the system prompt says email verification is enabled, do NOT use AuthView for the sign-up page — you must build a custom sign-up form instead (see the email verification guide). You may still use AuthView for the sign-in page.
export const dynamicParams = false;
export default async function AuthPage({ params, }: { params: Promise<{ path: string }>; }) { const { path } = await params;
return <AuthView path={path} />; } </code-template>
<code-template label="root-layout-with-auth" file="app/layout.tsx" language="tsx"> import { authClient } from '@/lib/auth/client'; import { NeonAuthUIProvider, UserButton, } from '@neondatabase/auth/react';export default function RootLayout({ children, }: { children: React.ReactNode; }) { return ( {/_ Set defaultTheme to match the app's theme: "light", "dark", or "system" if the app uses system-based switching _/} <NeonAuthUIProvider authClient={authClient} defaultTheme="light">
<header> <UserButton /> </header> {children} </NeonAuthUIProvider> ); } </code-template>.env.local)NEON_AUTH_BASE_URL=https://ep-xxx.neonauth.us-east-1.aws.neon.tech/neondb/auth NEON_AUTH_COOKIE_SECRET=your-cookie-secret-here </code-template>
</nextjs-only>