Skip to main content

neon-auth-nextjs

Sets up Neon Auth in Next.js App Router applications. Configures API routes, middleware, server components, and UI. Use when adding auth-only to Next.js apps (no database needed).

Zur Installation springen

Quellinformationen

Repository
neondatabase/neon-js
Letzte Quellaktivität
29. Januar 2026 um 12:32
Erkannte Sprache von SKILL.md
Englisch
Sterne
16
Forks
15

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
neon-auth-nextjs
description
Sets up Neon Auth in Next.js App Router applications. Configures API routes, middleware, server components, and UI. Use when adding auth-only to Next.js apps (no database needed).
allowed-tools
["Bash","Write","Read","Edit","Glob","Grep"]
# Neon Auth for Next.js Help developers set up @neondatabase/auth in Next.js App Router applications (auth only, no database). ## When to Use Use this skill when: - Setting up Neon Auth in Next.js (App Router) - User mentions "next.js", "next", or "app router" with Neon Auth - Auth-only setup (no database needed) ## Critical Rules 1. **Server vs Client imports**: Use correct import paths 2. **`'use client'` directive**: Required for client components using hooks 3. **CSS Import**: Choose ONE - either `/ui/css` OR `/ui/tailwind`, never both 4. **onSessionChange**: Always call `router.refresh()` to update Server Components ## Critical Imports | Purpose | Import From | |---------|-------------| | Unified Server (`createNeonAuth`) | `@neondatabase/auth/next/server` | | Client Auth | `@neondatabase/auth/next` | | UI Components | `@neondatabase/auth/react/ui` | | View Paths (static params) | `@neondatabase/auth/react/ui/server` | **Note**: Use `createNeonAuth()` from `@neondatabase/auth/next/server` to get a unified `auth` instance that provides: - `.handler()` - API route handler - `.middleware()` - Route protection middleware - All Better Auth server methods (`.signIn`, `.signUp`, `.getSession`, etc.) --- ## Setup ### 1. Install ```bash npm install @neondatabase/auth ``` ### 2. Environment (`.env.local`) ``` NEON_AUTH_BASE_URL=https://your-auth.neon.tech NEON_AUTH_COOKIE_SECRET=your-secret-at-least-32-characters-long ``` **Important**: Generate a secure secret (32+ characters) for production: ```bash openssl rand -base64 32 ``` ### 3. Server Setup (`lib/auth/server.ts`) Create a auth instance that provides handler, middleware, and server methods: ```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!, sessionDataTtl: 300, // Optional: session data cache TTL in seconds (default: 300 = 5 min) domain: '.example.com', // Optional: for cross-subdomain cookies }, }); ``` ### 4. API Route (`app/api/auth/[...path]/route.ts`) ```typescript import { auth } from '@/lib/auth/server'; export const { GET, POST } = auth.handler(); ``` ### 5. Middleware (`middleware.ts`) ```typescript import { auth } from '@/lib/auth/server'; export default auth.middleware({ loginUrl: '/auth/sign-in', }); export const config = { matcher: ['/dashboard/:path*', '/account/:path*'], }; ``` ### 6. Client (`lib/auth/client.ts`) ```typescript 'use client'; import { createAuthClient } from '@neondatabase/auth/next'; export const authClient = createAuthClient(); ``` ### 7. Provider (`app/providers.tsx`) ```typescript 'use client'; import { NeonAuthUIProvider } from '@neondatabase/auth/react/ui'; import Link from 'next/link'; import { useRouter } from 'next/navigation'; import { authClient } from '@/lib/auth/client'; export function Providers({ children }: { children: React.ReactNode }) { const router = useRouter(); return ( <NeonAuthUIProvider authClient={authClient} navigate={router.push} replace={router.replace} onSessionChange={() => router.refresh()} redirectTo="/dashboard" Link={({href, children}) => <Link to={href}>{children}</Link>} > {children} </NeonAuthUIProvider> ); } ``` ### 8. Layout (`app/layout.tsx`) ```typescript import { Providers } from './providers'; import '@neondatabase/auth/ui/css'; export default function RootLayout({ children }: { children: React.ReactNode }) { return ( <html lang="en"> <body> <Providers>{children}</Providers> </body> </html> ); } ``` ### 9. Auth Pages (`app/auth/[path]/page.tsx`) ```typescript import { AuthView } from '@neondatabase/auth/react/ui'; import { authViewPaths } from '@neondatabase/auth/react/ui/server'; export function generateStaticParams() { return Object.values(authViewPaths).map((path) => ({ path })); } export default async function AuthPage({ params }: { params: Promise<{ path: string }> }) { const { path } = await params; return <AuthView pathname={path} />; } ``` --- ## CSS & Styling ### Import Options **Without Tailwind** (pre-built CSS bundle ~47KB): ```typescript // app/layout.tsx import '@neondatabase/auth/ui/css'; ``` **With Tailwind CSS v4** (`app/globals.css`): ```css @import 'tailwindcss'; @import '@neondatabase/auth/ui/tailwind'; ``` **IMPORTANT**: Never import both - causes duplicate styles. ### Dark Mode The provider includes `next-themes`. Control via `defaultTheme` prop: ```typescript <NeonAuthUIProvider defaultTheme="system" // 'light' | 'dark' | 'system' // ... > ``` ### Custom Theming Override CSS variables in `globals.css`: ```css :root { --primary: hsl(221.2 83.2% 53.3%); --primary-foreground: hsl(210 40% 98%); --background: hsl(0 0% 100%); --foreground: hsl(222.2 84% 4.9%); --card: hsl(0 0% 100%); --card-foreground: hsl(222.2 84% 4.9%); --border: hsl(214.3 31.8% 91.4%); --input: hsl(214.3 31.8% 91.4%); --ring: hsl(221.2 83.2% 53.3%); --radius: 0.5rem; } .dark { --background: hsl(222.2 84% 4.9%); --foreground: hsl(210 40% 98%); /* ... dark mode overrides */ } ``` --- ## NeonAuthUIProvider Props Full configuration options: ```typescript <NeonAuthUIProvider // Required authClient={authClient} // Navigation (Next.js specific) navigate={router.push} // router.push for navigation replace={router.replace} // router.replace for redirects onSessionChange={() => router.refresh()} // Refresh Server Components! redirectTo="/dashboard" // Where to redirect after auth Link={({href, children}) => <Link to={href}>{children}</Link>} // Next.js Link component // Social/OAuth Providers social={{ providers: ['google'], }} // Feature Flags emailOTP={true} // Enable email OTP sign-in emailVerification={true} // Require email verification magicLink={false} // Magic link (disabled by default) multiSession={false} // Multiple sessions (disabled) // Credentials Configuration credentials={{ forgotPassword: true, // Show forgot password link }} // Sign Up Fields signUp={{ fields: ['name'], // Additional fields: 'name', 'username', etc. }} // Account Settings Fields account={{ fields: ['image', 'name', 'company', 'age', 'newsletter'], }} // Organization Features organization={{}} // Enable org features // Dark Mode defaultTheme="system" // 'light' | 'dark' | 'system' // Custom Labels localization={{ SIGN_IN: 'Welcome Back', SIGN_UP: 'Create Account', FORGOT_PASSWORD: 'Forgot Password?', OR_CONTINUE_WITH: 'or continue with', }} > {children} </NeonAuthUIProvider> ``` --- ## Server Components (RSC) ### Get Session in Server Component ```typescript // NO 'use client' - this is a Server Component import { auth } from '@/lib/auth/server'; // Server components using `auth` methods must be rendered dynamically export const dynamic = 'force-dynamic' export async function Profile() { const { data: session } = await auth.getSession(); if (!session?.user) return <div>Not signed in</div>; return ( <div> <p>Hello, {session.user.name}</p> <p>Email: {session.user.email}</p> </div> ); } ``` ### Route Handler with Auth ```typescript // app/api/user/route.ts import { auth } from '@/lib/auth/server'; import { NextResponse } from 'next/server'; export async function GET() { const { data: session } = await auth.getSession(); if (!session?.user) { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); } return NextResponse.json({ user: session.user }); } ``` --- ## Server Actions Server actions use the same `auth` instance from `lib/auth/server.ts`: ### Sign In Action ```typescript // app/actions/auth.ts 'use server'; import { auth } from '@/lib/auth/server'; import { redirect } from 'next/navigation'; export async function signIn(formData: FormData) { const { error } = await auth.signIn.email({ email: formData.get('email') as string, password: formData.get('password') as string, }); if (error) { return { error: error.message }; } redirect('/dashboard'); } export async function signUp(formData: FormData) { const { error } = await auth.signUp.email({ email: formData.get('email') as string, password: formData.get('password') as string, name: formData.get('name') as string, }); if (error) { return { error: error.message }; } redirect('/dashboard'); } export async function signOut() { await auth.signOut(); redirect('/'); } ``` ### Available Server Methods The `auth` instance from `createNeonAuth()` provides all Better Auth server methods: ```typescript // Authentication auth.signIn.email({ email, password }) auth.signUp.email({ email, password, name }) auth.signOut() auth.getSession() // User Management auth.updateUser({ name, image }) // Organizations auth.organization.create({ name, slug }) auth.organization.list() // Admin (if enabled) auth.admin.listUsers() auth.admin.banUser({ userId }) ``` --- ## Client Components
Auf GitHub ansehen
Diese SKILL.md ist sehr gross, daher zeigt SkillsMP hier nur den ersten Abschnitt. Auf GitHub ansehen