# Neon Auth Setup - React SPA (Vite) Complete setup instructions for Neon Auth in React Single Page Applications (Vite, Create React App, etc.). --- ## 1. Install Package ```bash npm install @neondatabase/auth # Or: npm install @neondatabase/neon-js npm install react-router-dom # Required for UI components ``` ## 2. Environment Variables Create or update `.env`: **For Vite:** ```bash VITE_NEON_AUTH_URL=https://ep-xxx.neonauth.c-2.us-east-2.aws.neon.build/dbname/auth ``` **For Create React App:** ```bash REACT_APP_NEON_AUTH_URL=https://ep-xxx.neonauth.c-2.us-east-2.aws.neon.build/dbname/auth ``` **Where to find your Auth URL:** 1. Go to your Neon project dashboard 2. Navigate to the "Auth" tab 3. Copy the Auth URL ## 3. Auth Client Configuration Create `src/lib/auth-client.ts`: **For `@neondatabase/auth`:** ```typescript import { createAuthClient } from "@neondatabase/auth"; import { BetterAuthReactAdapter } from "@neondatabase/auth/react/adapters"; export const authClient = createAuthClient( import.meta.env.VITE_NEON_AUTH_URL, { adapter: BetterAuthReactAdapter() } ); ``` **For `@neondatabase/neon-js`:** ```typescript import { createClient } from "@neondatabase/neon-js"; import { BetterAuthReactAdapter } from "@neondatabase/neon-js/auth/react/adapters"; export const client = createClient({ auth: { adapter: BetterAuthReactAdapter(), url: import.meta.env.VITE_NEON_AUTH_URL, }, dataApi: { url: import.meta.env.VITE_NEON_DATA_API_URL, }, }); export const authClient = client.auth; ``` **Critical:** - `BetterAuthReactAdapter` must be imported from the `/react/adapters` subpath - The adapter must be called as a function: `BetterAuthReactAdapter()` ## 4. Use in Components ```typescript import { authClient } from "./lib/auth-client"; function App() { const session = authClient.useSession(); if (session.isPending) return
Loading...
; if (!session.data) return ; return ; } ``` --- ## 5. UI Provider Setup (Optional) Skip this section if you're building custom auth forms. Use this if you want pre-built UI components. ### 5a. Import CSS **CRITICAL:** Choose ONE import method. Never import both - it causes duplicate styles. **Check if the project uses Tailwind CSS** by looking for: - `tailwind.config.js` or `tailwind.config.ts` in the project root - `@import 'tailwindcss'` or `@tailwind` directives in CSS files - `tailwindcss` in package.json dependencies **If NOT using Tailwind** - Add to `src/main.tsx` or entry point: For `@neondatabase/auth`: ```typescript import '@neondatabase/auth/ui/css'; ``` For `@neondatabase/neon-js`: ```typescript import '@neondatabase/neon-js/ui/css'; ``` **If using Tailwind CSS v4** - Add to main CSS file (e.g., index.css): For `@neondatabase/auth`: ```css @import 'tailwindcss'; @import '@neondatabase/auth/ui/tailwind'; ``` For `@neondatabase/neon-js`: ```css @import 'tailwindcss'; @import '@neondatabase/neon-js/ui/tailwind'; ``` ### 5b. Update main.tsx with BrowserRouter For `@neondatabase/auth`: ```tsx import { createRoot } from 'react-dom/client'; import { BrowserRouter } from 'react-router-dom'; import '@neondatabase/auth/ui/css'; // if not using Tailwind import App from './App'; import { Providers } from './providers'; createRoot(document.getElementById('root')!).render( ); ``` For `@neondatabase/neon-js`: ```tsx import { createRoot } from 'react-dom/client'; import { BrowserRouter } from 'react-router-dom'; import '@neondatabase/neon-js/ui/css'; // if not using Tailwind import App from './App'; import { Providers } from './providers'; createRoot(document.getElementById('root')!).render( ); ``` ### 5c. Create Auth Provider Create `src/providers.tsx`: For `@neondatabase/auth`: ```tsx import { NeonAuthUIProvider } from '@neondatabase/auth/react/ui'; import { useNavigate, Link as RouterLink } from 'react-router-dom'; import { authClient } from './lib/auth-client'; import type { ReactNode } from 'react'; // Adapter for react-router-dom Link function Link({ href, ...props }: { href: string } & React.AnchorHTMLAttributes) { return ; } export function Providers({ children }: { children: ReactNode }) { const navigate = useNavigate(); return ( navigate(path)} replace={(path) => navigate(path, { replace: true })} onSessionChange={() => { // Optional: refresh data or invalidate cache }} Link={Link} social={{ providers: ['google', 'github'] }} > {children} ); } ``` For `@neondatabase/neon-js`: ```tsx import { NeonAuthUIProvider } from '@neondatabase/neon-js/auth/react/ui'; import { useNavigate, Link as RouterLink } from 'react-router-dom'; import { authClient } from './lib/auth-client'; import type { ReactNode } from 'react'; // Adapter for react-router-dom Link function Link({ href, ...props }: { href: string } & React.AnchorHTMLAttributes) { return ; } export function Providers({ children }: { children: ReactNode }) { const navigate = useNavigate(); return ( navigate(path)} replace={(path) => navigate(path, { replace: true })} onSessionChange={() => { // Optional: refresh data or invalidate cache }} Link={Link} social={{ providers: ['google', 'github'] }} > {children} ); } ``` **Provider props explained:** - `navigate`: Function to navigate to a new route - `replace`: Function to replace current route (for redirects) - `onSessionChange`: Callback when auth state changes (useful for cache invalidation) - `Link`: Adapter component for react-router-dom's Link - `social`: Show Google and GitHub sign-in buttons (both enabled by default in Neon) ### 5d. Add Routes to App.tsx For `@neondatabase/auth`: ```tsx import { Routes, Route, useParams } from 'react-router-dom'; import { AuthView, UserButton, SignedIn, SignedOut } from '@neondatabase/auth/react/ui'; // Auth page - handles /auth/sign-in, /auth/sign-up, etc. function AuthPage() { const { pathname } = useParams(); return (
); } // Simple navbar example function Navbar() { return ( ); } function HomePage() { return
Welcome to My App!
; } export default function App() { return ( <> } /> } /> ); } ``` For `@neondatabase/neon-js`: ```tsx import { Routes, Route, useParams } from 'react-router-dom'; import { AuthView, UserButton, SignedIn, SignedOut } from '@neondatabase/neon-js/auth/react/ui'; // Auth page - handles /auth/sign-in, /auth/sign-up, etc. function AuthPage() { const { pathname } = useParams(); return (
); } // Simple navbar example function Navbar() { return ( ); } function HomePage() { return
Welcome to My App!
; } export default function App() { return ( <> } /> } /> ); } ``` **Auth routes created:** - `/auth/sign-in` - Sign in page - `/auth/sign-up` - Sign up page - `/auth/forgot-password` - Password reset request - `/auth/reset-password` - Set new password - `/auth/sign-out` - Sign out - `/auth/callback` - OAuth callback (internal) --- ## Package Selection | Need | Package | Bundle Size | |------|---------|-------------| | Auth only | `@neondatabase/auth` | Smaller (~50KB) | | Auth + Database queries | `@neondatabase/neon-js` | Full (~150KB) | **Recommendation:** Use `@neondatabase/auth` if you only need authentication. Use `@neondatabase/neon-js` if you also need PostgREST-style database queries. --- ## Related References - [UI Components - React SPA](https://raw.githubusercontent.com/neondatabase-labs/ai-rules/main/references/neon-auth-ui-react-spa.md) - React SPA UI provider setup - [Common Mistakes](https://raw.githubusercontent.com/neondatabase-labs/ai-rules/main/references/neon-auth-common-mistakes.md) - Import paths, adapter patterns - [Troubleshooting Guide](https://raw.githubusercontent.com/neondatabase-labs/ai-rules/main/references/neon-auth-troubleshooting.md) - Error solutions - [Code Generation Rules](https://raw.githubusercontent.com/neondatabase-labs/ai-rules/main/references/code-generation-rules.md) - Import and CSS strategies --- **Reference Version**: 1.1.0 **Last Updated**: 2025-12-16