Skip to main content

neon-js-react

Sets up the full Neon SDK with authentication AND database queries in React apps (Vite, CRA). Creates typed client, generates database types, and configures auth UI. Use for auth + database integration.

Ir para a instalação

Informações da origem

Repositório
neondatabase/neon-js
Última atividade na origem
22 de janeiro de 2026 às 11:01
Idioma detectado do SKILL.md
inglês
Estrelas
16
Forks
15

Opções de instalação

Por padrão, está selecionado o prompt que primeiro revisa a origem. Você pode mudar para um comando direto ou baixar uma cópia local.

Revise os arquivos de origem

Leia o SKILL.md e os arquivos complementares exibidos pelo SkillsMP antes de decidir se vai instalar.

Exibindo SKILL.md

SKILL.md
Instruções da origem · Visualização somente leitura
name
neon-js-react
description
Sets up the full Neon SDK with authentication AND database queries in React apps (Vite, CRA). Creates typed client, generates database types, and configures auth UI. Use for auth + database integration.
allowed-tools
["Bash","Write","Read","Edit","Glob","Grep"]
# Neon JS for React Help developers set up @neondatabase/neon-js with authentication AND database queries in React applications (Vite, CRA, etc.). ## When to Use Use this skill when: - Setting up Neon Auth + Database in a React app (Vite, CRA, etc.) - User needs both authentication AND database queries - User mentions "neon-js", "neon auth + database", or "full neon SDK" - User is NOT using Next.js (for Next.js, use `neon-auth-nextjs` as a starting point and add Data API configuration, or see `examples/nextjs-neon-auth/`) ## Critical Rules 1. **Adapter Factory Pattern**: Always call adapters with `()` ```typescript adapter: SupabaseAuthAdapter() // Correct adapter: SupabaseAuthAdapter // Wrong - missing () ``` 2. **React Adapter Import**: NOT exported from main - use subpath ```typescript import { BetterAuthReactAdapter } from '@neondatabase/neon-js/auth/react/adapters'; ``` 3. **Type Safety**: Always use Database generic for type-safe queries ```typescript const client = createClient<Database>({...}); ``` 4. **CSS Import**: Choose ONE - either `/ui/css` OR `/ui/tailwind`, never both --- ## Setup ### 1. Install ```bash npm install @neondatabase/neon-js ``` ### 2. Generate Database Types ```bash npx neon-js gen-types --db-url "postgresql://user:pass@host:5432/db" --output src/database.types.ts ``` **CLI Options:** ```bash npx neon-js gen-types --db-url <url> [options] # Required --db-url <url> Database connection string # Optional --output, -o <path> Output file (default: database.types.ts) --schema, -s <name> Schema to include (repeatable, default: public) --postgrest-v9-compat Disable one-to-one relationship detection --query-timeout <duration> Query timeout (e.g., 30s, 1m, default: 15s) ``` ### 3. Create Client (`src/client.ts`) ```typescript import { createClient } from '@neondatabase/neon-js'; import type { Database } from './database.types'; export const neonClient = createClient<Database>({ auth: { url: import.meta.env.VITE_NEON_AUTH_URL, // allowAnonymous: true, // Enable for RLS access without login }, dataApi: { url: import.meta.env.VITE_NEON_DATA_API_URL, }, }); ``` ### 4. Create Provider (`src/providers.tsx`) ```typescript import { NeonAuthUIProvider } from '@neondatabase/neon-js/auth/react'; import { useNavigate } from 'react-router-dom'; import { Link } from 'react-router-dom'; import { neonClient } from './client'; // Import CSS (choose one) import '@neondatabase/neon-js/ui/css'; export function Providers({ children }: { children: React.ReactNode }) { const navigate = useNavigate(); return ( <NeonAuthUIProvider authClient={neonClient.auth} navigate={navigate} redirectTo="/dashboard" Link={({href, children}) => <Link to={href}>{children}</Link>} > {children} </NeonAuthUIProvider> ); } ``` ### 5. Wrap App (`src/main.tsx`) ```typescript import { BrowserRouter } from 'react-router-dom'; import { Providers } from './providers'; import App from './App'; createRoot(document.getElementById('root')!).render( <BrowserRouter> <Providers> <App /> </Providers> </BrowserRouter> ); ``` ### 6. Environment Variables (`.env.local`) ``` VITE_NEON_AUTH_URL=https://your-auth.neon.tech VITE_NEON_DATA_API_URL=https://your-data-api.neon.tech/rest/v1 ``` --- ## CSS & Styling ### Import Options **Without Tailwind** (pre-built CSS bundle ~47KB): ```typescript // In provider or main.tsx import '@neondatabase/neon-js/ui/css'; ``` **With Tailwind CSS v4**: ```css @import 'tailwindcss'; @import '@neondatabase/neon-js/ui/tailwind'; ``` **IMPORTANT**: Never import both - causes duplicate styles. ### Dark Mode ```typescript <NeonAuthUIProvider defaultTheme="system" // 'light' | 'dark' | 'system' // ... > ``` ### Custom Theming Override CSS variables in your stylesheet: ```css :root { --primary: oklch(0.7 0.15 250); --primary-foreground: oklch(0.98 0 0); --background: oklch(1 0 0); --foreground: oklch(0.1 0 0); --card: oklch(1 0 0); --border: oklch(0.9 0 0); --radius: 0.5rem; } .dark { --background: oklch(0.15 0 0); --foreground: oklch(0.98 0 0); } ``` --- ## NeonAuthUIProvider Props Full configuration: ```typescript <NeonAuthUIProvider // Required authClient={neonClient.auth} // Note: .auth property of neonClient // Navigation navigate={navigate} Link={({href, children}) => <Link to={href}>{children}</Link>} redirectTo="/dashboard" // Social/OAuth social={{ providers: ['google'], }} // Feature Flags emailOTP={true} emailVerification={true} magicLink={false} multiSession={false} credentials={{ forgotPassword: true }} // Sign Up Fields signUp={{ fields: ['name'] }} // Account Fields account={{ fields: ['image', 'name', 'company'] }} // Organizations organization={{}} // Dark Mode defaultTheme="system" // Custom Labels localization={{ SIGN_IN: 'Welcome Back', SIGN_UP: 'Create Account', }} > {children} </NeonAuthUIProvider> ``` --- ## Database Queries ### Select ```typescript // Basic select const { data, error } = await neonClient .from('todos') .select('*'); // Select with filter const { data, error } = await neonClient .from('todos') .select('*') .eq('user_id', userId) .order('created_at', { ascending: false }); // Select with relations const { data, error } = await neonClient .from('posts') .select(` *, author:users(name, avatar), comments(id, content) `); // Single row const { data, error } = await neonClient .from('todos') .select('*') .eq('id', todoId) .single(); ``` ### Insert ```typescript // Single insert const { data, error } = await neonClient .from('todos') .insert({ title: 'New todo', user_id: userId }) .select() .single(); // Bulk insert const { data, error } = await neonClient .from('todos') .insert([ { title: 'Todo 1', user_id: userId }, { title: 'Todo 2', user_id: userId }, ]) .select(); ``` ### Update ```typescript const { data, error } = await neonClient .from('todos') .update({ completed: true }) .eq('id', todoId) .select() .single(); ``` ### Delete ```typescript const { error } = await neonClient .from('todos') .delete() .eq('id', todoId); ``` ### Upsert ```typescript const { data, error } = await neonClient .from('profiles') .upsert({ user_id: userId, bio: 'Updated bio' }) .select() .single(); ``` ### Filters ```typescript // Equality .eq('column', value) .neq('column', value) // Comparison .gt('column', value) // greater than .gte('column', value) // greater than or equal .lt('column', value) // less than .lte('column', value) // less than or equal // Pattern matching .like('column', '%pattern%') .ilike('column', '%pattern%') // case insensitive // Arrays .in('column', [1, 2, 3]) .contains('tags', ['javascript']) .containedBy('tags', ['javascript', 'typescript']) // Null .is('column', null) .not('column', 'is', null) // Range .range(0, 9) // pagination ``` ### Ordering & Pagination ```typescript const { data, error } = await neonClient .from('posts') .select('*') .order('created_at', { ascending: false }) .range(0, 9) // First 10 items .limit(10); ``` --- ## Auth Methods ### Default API (BetterAuth) ```typescript // Sign up await neonClient.auth.signUp.email({ email, password, name }); // Sign in await neonClient.auth.signIn.email({ email, password }); // OAuth await neonClient.auth.signIn.social({ provider: 'google', callbackURL: '/dashboard', }); // Get session const session = await neonClient.auth.getSession(); // Sign out await neonClient.auth.signOut(); ``` ### With SupabaseAuthAdapter ```typescript import { createClient, SupabaseAuthAdapter } from '@neondatabase/neon-js'; const neonClient = createClient<Database>({ auth: { url: import.meta.env.VITE_NEON_AUTH_URL, adapter: SupabaseAuthAdapter(), }, dataApi: { url: import.meta.env.VITE_NEON_DATA_API_URL, }, }); // Supabase-style methods await neonClient.auth.signUp({ email, password, options: { data: { name } } }); await neonClient.auth.signInWithPassword({ email, password }); await neonClient.auth.signInWithOAuth({ provider: 'google', options: { redirectTo } }); const { data: session } = await neonClient.auth.getSession(); await neonClient.auth.signOut(); // Event listener neonClient.auth.onAuthStateChange((event, session) => { console.log(event); // 'SIGNED_IN', 'SIGNED_OUT', 'TOKEN_REFRESHED' }); ``` ### With BetterAuthReactAdapter ```typescript import { createClient } from '@neondatabase/neon-js'; import { BetterAuthReactAdapter } from '@neondatabase/neon-js/auth/react/adapters';
Ver no GitHub
Este SKILL.md e muito grande, entao o SkillsMP mostra aqui apenas a primeira secao. Ver no GitHub